python - groupby - pandas group by multiple columns
¿Cuál es la diferencia entre pandas agg y función de aplicación? (3)
No puedo entender la diferencia entre las funciones .aggregate
y .apply
Pandas.
Tome como ejemplo lo siguiente: cargue un conjunto de datos, groupby
un groupby
, defino una función simple y el usuario .agg
o .apply
.
Como puede ver, la declaración de impresión dentro de mi función produce el mismo resultado después de usar .agg
y .apply
. El resultado, por otro lado, es diferente. ¿Porqué es eso?
import pandas
import pandas as pd
iris = pd.read_csv(''iris.csv'')
by_species = iris.groupby(''Species'')
def f(x):
...: print type(x)
...: print x.head(3)
...: return 1
Utilizando apply
:
by_species.apply(f)
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#0 5.1 3.5 1.4 0.2 setosa
#1 4.9 3.0 1.4 0.2 setosa
#2 4.7 3.2 1.3 0.2 setosa
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#0 5.1 3.5 1.4 0.2 setosa
#1 4.9 3.0 1.4 0.2 setosa
#2 4.7 3.2 1.3 0.2 setosa
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#50 7.0 3.2 4.7 1.4 versicolor
#51 6.4 3.2 4.5 1.5 versicolor
#52 6.9 3.1 4.9 1.5 versicolor
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#100 6.3 3.3 6.0 2.5 virginica
#101 5.8 2.7 5.1 1.9 virginica
#102 7.1 3.0 5.9 2.1 virginica
#Out[33]:
#Species
#setosa 1
#versicolor 1
#virginica 1
#dtype: int64
Usando agg
by_species.agg(f)
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#0 5.1 3.5 1.4 0.2 setosa
#1 4.9 3.0 1.4 0.2 setosa
#2 4.7 3.2 1.3 0.2 setosa
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#50 7.0 3.2 4.7 1.4 versicolor
#51 6.4 3.2 4.5 1.5 versicolor
#52 6.9 3.1 4.9 1.5 versicolor
#<class ''pandas.core.frame.DataFrame''>
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species
#100 6.3 3.3 6.0 2.5 virginica
#101 5.8 2.7 5.1 1.9 virginica
#102 7.1 3.0 5.9 2.1 virginica
#Out[34]:
# Sepal.Length Sepal.Width Petal.Length Petal.Width
#Species
#setosa 1 1 1 1
#versicolor 1 1 1 1
#virginica 1 1 1 1
( Nota: estas comparaciones son relevantes para los objetos DataframeGroupby )
Algunas ventajas plausibles de usar .agg () en comparación con .apply (), para los objetos DataFrame GroupBy serían:
1) .agg () brinda la flexibilidad de aplicar múltiples funciones a la vez , o pasar una lista de funciones a cada columna.
2) También, aplicando diferentes funciones a la vez a diferentes columnas de dataframe.
Eso significa que tienes bastante control sobre cada columna con cada operación.
Aquí está el enlace para obtener más información: http://pandas.pydata.org/pandas-docs/version/0.13.1/groupby.html
Sin embargo, la función de aplicación podría limitarse para aplicar una función a cada columna del marco de datos a la vez. Por lo tanto, es posible que deba llamar a la función de aplicación repetidamente para llamar a diferentes operaciones a la misma columna.
Aquí hay algunos ejemplos de comparación para .apply () vs .agg () para los objetos DataframeGroupBy:
Veamos, primero, las operaciones usando .apply ():
In [261]: df = pd.DataFrame({"name":["Foo", "Baar", "Foo", "Baar"], "score_1":[5,10,15,10], "score_2" :[10,15,10,25], "score_3" : [10,20,30,40]})
In [262]: df
Out[262]:
name score_1 score_2 score_3
0 Foo 5 10 10
1 Baar 10 15 20
2 Foo 15 10 30
3 Baar 10 25 40
In [263]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.sum())
Out[263]:
name score_1
Baar 10 40
Foo 5 10
15 10
Name: score_2, dtype: int64
In [264]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.min())
Out[264]:
name score_1
Baar 10 15
Foo 5 10
15 10
Name: score_2, dtype: int64
In [265]: df.groupby(["name", "score_1"])["score_2"].apply(lambda x : x.mean())
Out[265]:
name score_1
Baar 10 20.0
Foo 5 10.0
15 10.0
Name: score_2, dtype: float64
Ahora, mira las mismas operaciones usando .agg () sin esfuerzo:
In [274]: df = pd.DataFrame({"name":["Foo", "Baar", "Foo", "Baar"], "score_1":[5,10,15,10], "score_2" :[10,15,10,25], "score_3" : [10,20,30,40]})
In [275]: df
Out[275]:
name score_1 score_2 score_3
0 Foo 5 10 10
1 Baar 10 15 20
2 Foo 15 10 30
3 Baar 10 25 40
In [276]: df.groupby(["name", "score_1"]).agg({"score_3" :[np.sum, np.min, np.mean, np.max], "score_2":lambda x : x.mean()})
Out[276]:
score_2 score_3
<lambda> sum amin mean amax
name score_1
Baar 10 20 60 20 30 40
Foo 5 10 10 10 10 10
15 10 30 30 30 30
Por lo tanto, .agg () podría ser realmente útil para manejar los objetos DataFrameGroupBy, en comparación con .apply (). Pero, si está manejando únicamente objetos de marco de datos puro, y no objetos DataFrameGroupBy, apply () puede ser muy útil, ya que apply () puede aplicar una función a lo largo de cualquier eje del marco de datos.
(Por ejemplo, el eje = 0 implica una operación a nivel de columnas con .apply (), que es un modo predeterminado, y el eje = 1 implicaría una operación a lo largo de las filas al tratar con objetos de marco de datos puros)
Al usar aplicar a un grupo, he encontrado que .apply devolverá las columnas agrupadas. Hay una nota en la documentación (pandas.pydata.org/pandas-docs/stable/groupby.html):
"... Por lo tanto, las columnas agrupadas pueden incluirse en la salida, así como establecer los índices".
.aggregate no devolverá las columnas agrupadas.
apply
aplica la función a cada grupo (sus Species
). Su función devuelve 1, por lo que termina con 1 valor para cada uno de los 3 grupos.
agg
agrega cada columna (característica) para cada grupo, por lo que usted termina con un valor por columna por grupo.
Lee los documentos del grupo, son muy útiles. También hay un montón de tutoriales flotando alrededor de la web.