He estado muy confundido acerca de cómo se definen los ejes de Python y si se refieren a filas o columnas de un DataFrame. Considere el siguiente código:
>>> df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], columns=["col1", "col2", "col3", "col4"])
>>> df
col1 col2 col3 col4
0 1 1 1 1
1 2 2 2 2
2 3 3 3 3
Entonces, si llamamos df.mean(axis=1)
, obtendremos una media en las filas:
>>> df.mean(axis=1)
0 1
1 2
2 3
Sin embargo, si llamamos df.drop(name, axis=1)
, en realidad soltamos una columna , no una fila:
>>> df.drop("col4", axis=1)
col1 col2 col3
0 1 1 1
1 2 2 2
2 3 3 3
¿Alguien puede ayudarme a comprender qué se entiende por "eje" en pandas / numpy / scipy?
Una nota al margen, DataFrame.mean
podría definirse mal. Dice en la documentación DataFrame.mean
que axis=1
se supone que significa una media sobre las columnas, no las filas ...
mean
y losdrop
. Se necesita un pensamiento no lineal para llegar a la conducta real.Respuestas:
Quizás sea más simple recordarlo como 0 = hacia abajo y 1 = a lo ancho .
Esto significa:
axis=0
para aplicar un método en cada columna o en las etiquetas de las filas (el índice).axis=1
para aplicar un método en cada fila o en las etiquetas de las columnas.Aquí hay una imagen para mostrar las partes de un DataFrame a las que se refiere cada eje:
También es útil recordar que Pandas sigue el uso que hace NumPy de la palabra
axis
. El uso se explica en el glosario de términos de NumPy :Entonces, con respecto al método en la pregunta
df.mean(axis=1)
, parece estar correctamente definido. Toma la media de las entradas horizontalmente en las columnas , es decir, a lo largo de cada fila individual. Por otro lado,df.mean(axis=0)
sería una operación que actúe verticalmente hacia abajo a través de filas .Del mismo modo, se
df.drop(name, axis=1)
refiere a una acción en las etiquetas de las columnas, ya que atraviesan intuitivamente el eje horizontal. Especificaraxis=0
haría que el método actúe en filas.fuente
df.apply
como similar a un método comodf.sum
. Por ejemplo,df.sum(axis=0)
suma cada columna del DataFrame. Del mismo modo, puede escribirdf.apply(sum, axis=0)
para realizar exactamente la misma operación. Si bien la operación se aplica a cada columna en el DataFrame, la función real se ejecuta en el eje 0.MARGIN
(similar aaxis
en pandas) de "1" corresponde a "filas", lo que significa que la función se aplica a cada fila , mientras que la un valor mayor de "2" se refiere a "columnas", lo que significa que la función se aplica a cada columna .Otra forma de explicar:
// Not realistic but ideal for understanding the axis parameter df = pd.DataFrame([[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3]], columns=["idx1", "idx2", "idx3", "idx4"], index=["idx1", "idx2", "idx3"] ) ---------------------------------------1 | idx1 idx2 idx3 idx4 | idx1 1 1 1 1 | idx2 2 2 2 2 | idx3 3 3 3 3 0
Acerca de
df.drop
(el eje significa la posición)A: I wanna remove idx3. B: **Which one**? // typing while waiting response: df.drop("idx3", A: The one which is on axis 1 B: OK then it is >> df.drop("idx3", axis=1) // Result ---------------------------------------1 | idx1 idx2 idx4 | idx1 1 1 1 | idx2 2 2 2 | idx3 3 3 3 0
Acerca de
df.apply
(eje significa dirección)A: I wanna apply sum. B: Which direction? // typing while waiting response: df.apply(lambda x: x.sum(), A: The one which is on *parallel to axis 0* B: OK then it is >> df.apply(lambda x: x.sum(), axis=0) // Result idx1 6 idx2 6 idx3 6 idx4 6
fuente
Ya hay respuestas adecuadas, pero les doy otro ejemplo con> 2 dimensiones.
El parámetro
axis
significa el eje que se va a cambiar .Por ejemplo, considere que hay un marco de datos con dimensión axbxc .
df.mean(axis=1)
devuelve un marco de datos con dimensión ax 1 xc .df.drop("col4", axis=1)
devuelve un marco de datos con dimensión ax (b-1) xc .Aquí,
axis=1
significa el segundo eje que esb
, por lo que elb
valor se cambiará en estos ejemplos.fuente
Debería ser más conocido que los alias de cadena 'índice' y 'columnas' pueden usarse en lugar de los enteros 0/1. Los alias son mucho más explícitos y me ayudan a recordar cómo se realizan los cálculos. Otro alias para 'índice' es 'filas' .
Cuando
axis='index'
se usa, los cálculos se realizan en las columnas, lo cual es confuso. Pero, lo recuerdo como obtener un resultado que es del mismo tamaño que otra fila.Pongamos algunos datos en la pantalla para ver de qué estoy hablando:
df = pd.DataFrame(np.random.rand(10, 4), columns=list('abcd')) a b c d 0 0.990730 0.567822 0.318174 0.122410 1 0.144962 0.718574 0.580569 0.582278 2 0.477151 0.907692 0.186276 0.342724 3 0.561043 0.122771 0.206819 0.904330 4 0.427413 0.186807 0.870504 0.878632 5 0.795392 0.658958 0.666026 0.262191 6 0.831404 0.011082 0.299811 0.906880 7 0.749729 0.564900 0.181627 0.211961 8 0.528308 0.394107 0.734904 0.961356 9 0.120508 0.656848 0.055749 0.290897
Cuando queremos tomar la media de todas las columnas, usamos
axis='index'
para obtener lo siguiente:df.mean(axis='index') a 0.562664 b 0.478956 c 0.410046 d 0.546366 dtype: float64
El mismo resultado se obtendría mediante:
df.mean() # default is axis=0 df.mean(axis=0) df.mean(axis='rows')
Para usar una operación de izquierda a derecha en las filas, use axis = 'columnas'. Lo recuerdo pensando que se puede agregar una columna adicional a mi DataFrame:
df.mean(axis='columns') 0 0.499784 1 0.506596 2 0.478461 3 0.448741 4 0.590839 5 0.595642 6 0.512294 7 0.427054 8 0.654669 9 0.281000 dtype: float64
El mismo resultado se obtendría mediante:
df.mean(axis=1)
Agregue una nueva fila con eje = 0 / índice / filas
Usemos estos resultados para agregar filas o columnas adicionales para completar la explicación. Entonces, siempre que use axis = 0 / index / rows, es como obtener una nueva fila del DataFrame. Agreguemos una fila:
df.append(df.mean(axis='rows'), ignore_index=True) a b c d 0 0.990730 0.567822 0.318174 0.122410 1 0.144962 0.718574 0.580569 0.582278 2 0.477151 0.907692 0.186276 0.342724 3 0.561043 0.122771 0.206819 0.904330 4 0.427413 0.186807 0.870504 0.878632 5 0.795392 0.658958 0.666026 0.262191 6 0.831404 0.011082 0.299811 0.906880 7 0.749729 0.564900 0.181627 0.211961 8 0.528308 0.394107 0.734904 0.961356 9 0.120508 0.656848 0.055749 0.290897 10 0.562664 0.478956 0.410046 0.546366
Agregue una nueva columna con eje = 1 / columnas
De manera similar, cuando el eje = 1 / columnas, creará datos que se pueden convertir fácilmente en su propia columna:
df.assign(e=df.mean(axis='columns')) a b c d e 0 0.990730 0.567822 0.318174 0.122410 0.499784 1 0.144962 0.718574 0.580569 0.582278 0.506596 2 0.477151 0.907692 0.186276 0.342724 0.478461 3 0.561043 0.122771 0.206819 0.904330 0.448741 4 0.427413 0.186807 0.870504 0.878632 0.590839 5 0.795392 0.658958 0.666026 0.262191 0.595642 6 0.831404 0.011082 0.299811 0.906880 0.512294 7 0.749729 0.564900 0.181627 0.211961 0.427054 8 0.528308 0.394107 0.734904 0.961356 0.654669 9 0.120508 0.656848 0.055749 0.290897 0.281000
Parece que puede ver todos los alias con las siguientes variables privadas:
df._AXIS_ALIASES {'rows': 0} df._AXIS_NUMBERS {'columns': 1, 'index': 0} df._AXIS_NAMES {0: 'index', 1: 'columns'}
fuente
Cuando eje = 'filas' o eje = 0, significa elementos de acceso en la dirección de las filas, de arriba a abajo. Si aplica la suma a lo largo del eje = 0, nos dará los totales de cada columna.
Cuando eje = 'columnas' o eje = 1, significa elementos de acceso en la dirección de las columnas, de izquierda a derecha. Si aplica la suma a lo largo del eje = 1, obtendremos los totales de cada fila.
¡Todavía confuso! Pero lo anterior me lo pone un poco más fácil.
fuente
Encuentro todas las otras respuestas confusas. Así es como lo pienso:
Entonces
df.drop(name, axis=1)
: suelta una columnadf.mean(axis=1)
: calcula una columna (el resultado se puede agregar como una nueva columna)fuente