Tengo un marco de datos con este tipo de datos:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
0 18 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 84 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2 50 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
La forma df es (10000, 329)
Me gustaría convertir el 5% aleatorio de 1
en el marco de datos a 0
.
¿Es posible?
2 respuestas
Prueba esto:
# Get all columns from 1 to 328 and stack them into a temp series
tmp = df.loc[:, 1:].stack()
# Get the 1s
ones = tmp[tmp == 1].values.astype('int8')
# Mix with 5% zeros. You can use ceil or floor here
# as long as it makes an integer
n_zero = np.ceil(ones.shape[0] * .05).astype('int')
# Make the 0s
zeros = np.zeros(n_zero, dtype='int8')
# Replace 5% of the 1s with 0s and shuffle them
noise = np.concatenate((ones[n_zero:], zeros))
np.random.shuffle(noise)
# Assign the noise back to `tmp`
tmp.loc[tmp == 1] = noise
# Assign the noise back to the orignal frame
df.loc[:, 1:] = tmp.unstack()
Puede saber si el 5% de 1s ha sido reemplazado por 0s sumando los cuadros anterior y posterior:
# Run this before and after the last line above to verify
df.loc[:, 1:].values.sum()
Aquí hay una solución más larga en la que imprimo los distintos pasos.
Cree el conjunto de datos de muestra con numpy. Las dimensiones y los valores se modificarán de la pregunta para que la respuesta sea más clara. rawmat será una matriz de ceros y unos de 10 por 10, excepto la primera columna, que son valores más grandes. Entre los ceros y unos hay un 50 por ciento de probabilidad de que se obtenga uno.
import numpy as np
np.random.seed(1000)
rawmat = np.random.randint(2,size=(10,10))
# insert higher values in the first column
rawmat[:,0] = np.random.randint(low=5,high=9,size=10)
print(rawmat)
[[5 1 1 0 1 0 0 1 1 0]
[6 1 0 1 0 1 0 0 1 1]
[5 0 1 0 0 0 0 1 0 0]
[6 0 0 0 1 0 0 1 1 0]
[6 0 1 1 0 1 0 1 0 0]
[5 1 0 0 1 0 0 1 0 1]
[5 1 1 0 1 0 1 0 1 1]
[5 1 1 1 1 1 1 0 1 1]
[7 1 1 1 0 0 0 0 1 1]
[8 0 0 0 1 1 0 1 1 0]]
De 100 celdas, 90 son ahora cero o uno. De hecho, 46 son 1, lo cual es razonable dada la probabilidad del 50 por ciento.
np.count_nonzero(rawmat==1)
46
Podemos crear una máscara donde el 50 por ciento de las observaciones relevantes son verdaderas con randmask. Sin embargo, el truco en estas preguntas es centrarse solo en las preguntas, por lo que obtenemos esto con rawones.
randmask = np.random.choice(a=[False, True], size=(10,10),p=[0.5,0.5])
rawones = np.where(rawmat==1,rawmat,0)
onefin = np.where(randmask,onemask,np.zeros((10,10),dtype=int))
Ahora la cantidad de unidades disminuirá a la mitad. Inicialmente había 46 unos en rawmat y ahora hay 23 en onefine.
np.count_nonzero(onefin==1)
23
Los filtrados se pueden recombinar con los datos antiguos para obtener una matriz con la mitad de los.
finmat = np.where(rawmat==1,onefin,rawmat)
print(finmat)
[[5 0 0 0 0 0 0 1 1 0]
[6 1 0 1 0 0 0 0 1 0]
[5 0 1 0 0 0 0 1 0 0]
[6 0 0 0 0 0 0 1 0 0]
[6 0 0 1 0 0 0 0 0 0]
[5 1 0 0 1 0 0 0 0 1]
[5 0 1 0 1 0 1 0 0 0]
[5 1 0 0 1 1 0 0 1 1]
[7 1 1 0 0 0 0 0 0 0]
[8 0 0 0 0 1 0 0 0 0]]
Ahora tenemos la matriz original con el número de unidades reducidas a la mitad de 46 a 23.
np.count_nonzero(finmat==1)
23
Preguntas relacionadas
Nuevas preguntas
python
Python es un lenguaje de programación multipropósito, de tipificación dinámica y de múltiples paradigmas. Está diseñado para ser rápido de aprender, comprender y usar, y hacer cumplir una sintaxis limpia y uniforme. Tenga en cuenta que Python 2 está oficialmente fuera de soporte a partir del 01-01-2020. Aún así, para preguntas de Python específicas de la versión, agregue la etiqueta [python-2.7] o [python-3.x]. Cuando utilice una variante de Python (por ejemplo, Jython, PyPy) o una biblioteca (por ejemplo, Pandas y NumPy), inclúyala en las etiquetas.