python - recorrer - seleccionar columnas de un dataframe pandas
Reproducción aleatoria de filas de DataFrame (9)
Tengo el siguiente DataFrame:
Col1 Col2 Col3 Type
0 1 2 3 1
1 4 5 6 1
...
20 7 8 9 2
21 10 11 12 2
...
45 13 14 15 3
46 16 17 18 3
...
El DataFrame se lee desde un archivo csv.
Todas las filas que tienen
Type
1 están en la parte superior, seguidas por las filas con
Type
2, seguidas por las filas con
Type
3, etc.
Me gustaría barajar el orden de las filas del DataFrame, para que todos los
Type
se mezclen.
Un posible resultado podría ser:
Col1 Col2 Col3 Type
0 7 8 9 2
1 13 14 15 3
...
20 1 2 3 1
21 10 11 12 2
...
45 4 5 6 1
46 16 17 18 3
...
¿Cómo puedo conseguir esto?
AFAIK la solución más simple es:
df_shuffled = df.reindex(np.random.permutation(df.index))
Aquí hay otra forma:
df[''rnd''] = np.random.rand(len(df)) df = df.sort_values(by=''rnd'', inplace=True).drop(''rnd'', axis=1)
La forma más idiomática de hacer esto con los pandas es usar el método
.sample
de su marco de datos, es decir
df.sample(frac=1)
El argumento de la palabra clave
frac
especifica la fracción de filas a devolver en la muestra aleatoria, por lo que
frac=1
significa devolver todas las filas (en orden aleatorio).
Nota: Si desea barajar su marco de datos en el lugar y restablecer el índice, puede hacer, por ejemplo,
df = df.sample(frac=1).reset_index(drop=True)
Aquí, especificar
drop=True
evita que
.reset_index
cree una columna que contenga las entradas de índice antiguas.
Nota de seguimiento:
aunque puede no parecer que la operación anterior esté
en su lugar
, python / pandas es lo suficientemente inteligente como para no hacer otro malloc para el objeto barajado.
Es decir, aunque el objeto de
referencia
ha cambiado (con lo que quiero decir que
id(df_old)
no es lo mismo que
id(df_new)
), el objeto C subyacente sigue siendo el mismo.
Para mostrar que este es el caso, puede ejecutar un generador de perfiles de memoria simple:
$ python3 -m memory_profiler ./test.py
Filename: ./test.py
Line # Mem usage Increment Line Contents
================================================
5 68.5 MiB 68.5 MiB @profile
6 def shuffle():
7 847.8 MiB 779.3 MiB df = pd.DataFrame(np.random.randn(100, 1000000))
8 847.9 MiB 0.1 MiB df = df.sample(frac=1).reset_index(drop=True)
Lo que también es útil, si lo usa para Machine_learning y desea separar siempre los mismos datos, puede usar:
df.sample(n=len(df), random_state=42)
esto asegura que mantengas tu opción aleatoria siempre replicable
Puede barajar las filas de un marco de datos indexando con un índice barajado.
Para esto, puede usar, por ejemplo,
np.random.permutation
(pero
np.random.choice
también es una posibilidad):
In [12]: df = pd.read_csv(StringIO(s), sep="/s+")
In [13]: df
Out[13]:
Col1 Col2 Col3 Type
0 1 2 3 1
1 4 5 6 1
20 7 8 9 2
21 10 11 12 2
45 13 14 15 3
46 16 17 18 3
In [14]: df.iloc[np.random.permutation(len(df))]
Out[14]:
Col1 Col2 Col3 Type
46 16 17 18 3
45 13 14 15 3
20 7 8 9 2
0 1 2 3 1
1 4 5 6 1
21 10 11 12 2
Si desea mantener el índice numerado de 1, 2, .., n como en su ejemplo, simplemente puede restablecer el índice:
df_shuffled.reset_index(drop=True)
Simplemente puede usar sklearn para esto
from sklearn.utils import shuffle
df = shuffle(df)
baraja el marco de datos de pandas tomando una matriz de muestra en este caso índice y aleatoriza su orden y luego configura la matriz como un índice de marco de datos. Ahora ordene el marco de datos según el índice. Aquí va tu marco de datos barajado
import random
df = pd.DataFrame({"a":[1,2,3,4],"b":[5,6,7,8]})
index = [i for i in range(df.shape[0])]
random.shuffle(index)
df.set_index([index]).sort_index()
salida
a b
0 2 6
1 1 5
2 3 7
3 4 8
Inserte su marco de datos en el lugar mío en el código anterior.
(No tengo suficiente reputación para comentar esto en la publicación principal, así que espero que alguien más pueda hacer eso por mí). Hubo una preocupación que surgió del primer método:
df.sample(frac=1)
hizo una copia profunda o simplemente cambió el marco de datos. Ejecuté el siguiente código:
print(hex(id(df)))
print(hex(id(df.sample(frac=1))))
print(hex(id(df.sample(frac=1).reset_index(drop=True))))
y mis resultados fueron:
0x1f8a784d400
0x1f8b9d65e10
0x1f8b9d65b70
lo que significa que el método no devuelve el mismo objeto, como se sugirió en el último comentario. Entonces, este método realmente hace una copia barajada.
TL; DR
:
np.random.shuffle(ndarray)
puede hacer el trabajo.
Entonces, en tu caso
np.random.shuffle(DataFrame.values)
DataFrame
, bajo el capó, utiliza NumPy ndarray como soporte de datos.
(Puede verificar desde el
código fuente de DataFrame
)
Entonces, si usa
np.random.shuffle()
,
np.random.shuffle()
la matriz a lo largo del primer eje de una matriz multidimensional.
Pero el índice del
DataFrame
permanece sin mezclar.
Sin embargo, hay algunos puntos a considerar.
- La función no devuelve ninguno. En caso de que desee conservar una copia del objeto original, debe hacerlo antes de pasar a la función.
-
sklearn.utils.shuffle()
, como sugirió el usuario tj89, puede designarrandom_state
junto con otra opción para controlar la salida. Es posible que desee eso para fines de desarrollo. -
sklearn.utils.shuffle()
es más rápido. Pero CAMBIARÁ la información del eje (índice, columna) delDataFrame
junto con elndarray
que contiene.
Resultado de referencia
entre
sklearn.utils.shuffle()
y
np.random.shuffle()
.
ndarray
nd = sklearn.utils.shuffle(nd)
0.10793248389381915 seg. 8 veces más rápido
np.random.shuffle(nd)
0.8897626010002568 seg
Marco de datos
df = sklearn.utils.shuffle(df)
0.3183923360193148 seg. 3 veces más rápido
np.random.shuffle(df.values)
0.9357550159329548 sec
Conclusión: Si está bien ejemplificar la información (índice, columna) junto con ndarray, use
sklearn.utils.shuffle()
. De lo contrario, usenp.random.shuffle()
código usado
import timeit
setup = ''''''
import numpy as np
import pandas as pd
import sklearn
nd = np.random.random((1000, 100))
df = pd.DataFrame(nd)
''''''
timeit.timeit(''nd = sklearn.utils.shuffle(nd)'', setup=setup, number=1000)
timeit.timeit(''np.random.shuffle(nd)'', setup=setup, number=1000)
timeit.timeit(''df = sklearn.utils.shuffle(df)'', setup=setup, number=1000)
timeit.timeit(''np.random.shuffle(df.values)'', setup=setup, number=1000)
benchmarking python