functions - python pandas download windows
¿Cómo creo una nueva columna a partir de la salida de pandas groupby(). Sum()? (2)
¿Cómo creo una nueva columna con Groupby (). Sum ()?
Hay dos formas: una sencilla y la otra un poco más interesante.
Favorito de todos:
GroupBy.transform()
con
''sum''
La respuesta de @Ed Chum se puede simplificar, un poco.
Llame a
DataFrame.groupby
lugar de
Series.groupby
.
Esto da como resultado una sintaxis más simple.
# The setup.
df[[''Date'', ''Data3'']]
Date Data3
0 2015-05-08 5
1 2015-05-07 8
2 2015-05-06 6
3 2015-05-05 1
4 2015-05-08 50
5 2015-05-07 100
6 2015-05-06 60
7 2015-05-05 120
df.groupby(''Date'')[''Data3''].transform(''sum'')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Es un poco más rápido
df2 = pd.concat([df] * 12345)
%timeit df2[''Data3''].groupby(df[''Date'']).transform(''sum'')
%timeit df2.groupby(''Date'')[''Data3''].transform(''sum'')
10.4 ms ± 367 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
8.58 ms ± 559 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
No convencional, pero vale la pena considerarlo:
GroupBy.sum()
+
Series.map()
Me topé con una idiosincrasia interesante en la API.
Por lo que digo, puede reproducir esto en cualquier versión principal de más de 0.20 (probé esto en 0.23 y 0.24).
Parece que siempre puede ahorrar unos pocos milisegundos del tiempo que tarda la
transform
si en su lugar usa una función directa de
GroupBy
y la difunde usando el
map
:
df.Date.map(df.groupby(''Date'')[''Data3''].sum())
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Date, dtype: int64
Comparar con
df.groupby(''Date'')[''Data3''].transform(''sum'')
0 55
1 108
2 66
3 121
4 55
5 108
6 66
7 121
Name: Data3, dtype: int64
Mis pruebas muestran que el
map
es un poco más rápido si puede permitirse usar la función directa
GroupBy
(como
mean
,
min
,
max
,
first
, etc.).
Es más o menos más rápido para la mayoría de las situaciones generales hasta alrededor de ~ 200 mil registros.
Después de eso, el rendimiento realmente depende de los datos.
(Izquierda: v0.23, Derecha: v0.24)
Una buena alternativa para saber, y mejor si tiene marcos más pequeños con un número menor de grupos.
.
.
pero recomendaría
transform
como primera opción.
Pensé que valía la pena compartir esto de todos modos.
Código de referencia, para referencia:
import perfplot
perfplot.show(
setup=lambda n: pd.DataFrame({''A'': np.random.choice(n//10, n), ''B'': np.ones(n)}),
kernels=[
lambda df: df.groupby(''A'')[''B''].transform(''sum''),
lambda df: df.A.map(df.groupby(''A'')[''B''].sum()),
],
labels=[''GroupBy.transform'', ''GroupBy.sum + map''],
n_range=[2**k for k in range(5, 20)],
xlabel=''N'',
logy=True,
logx=True
)
Intentando crear una nueva columna a partir del cálculo
groupby
.
En el código a continuación, obtengo los valores calculados correctos para cada fecha (ver el grupo a continuación) pero cuando intento crear una nueva columna (
df[''Data4'']
) consigo NaN.
Así que estoy tratando de crear una nueva columna en el marco de datos con la suma de
Data3
para todas las fechas y aplicarla a cada fila de fecha.
Por ejemplo, 2015-05-08 está en 2 filas (el total es 50 + 5 = 55) y en esta nueva columna me gustaría tener 55 en ambas filas.
import pandas as pd
import numpy as np
from pandas import DataFrame
df = pd.DataFrame({''Date'': [''2015-05-08'', ''2015-05-07'', ''2015-05-06'', ''2015-05-05'', ''2015-05-08'', ''2015-05-07'', ''2015-05-06'', ''2015-05-05''], ''Sym'': [''aapl'', ''aapl'', ''aapl'', ''aapl'', ''aaww'', ''aaww'', ''aaww'', ''aaww''], ''Data2'': [11, 8, 10, 15, 110, 60, 100, 40],''Data3'': [5, 8, 6, 1, 50, 100, 60, 120]})
group = df[''Data3''].groupby(df[''Date'']).sum()
df[''Data4''] = group
Desea usar
transform
this devolverá una serie con el índice alineado al df para que luego pueda agregarlo como una nueva columna:
In [74]:
df = pd.DataFrame({''Date'': [''2015-05-08'', ''2015-05-07'', ''2015-05-06'', ''2015-05-05'', ''2015-05-08'', ''2015-05-07'', ''2015-05-06'', ''2015-05-05''], ''Sym'': [''aapl'', ''aapl'', ''aapl'', ''aapl'', ''aaww'', ''aaww'', ''aaww'', ''aaww''], ''Data2'': [11, 8, 10, 15, 110, 60, 100, 40],''Data3'': [5, 8, 6, 1, 50, 100, 60, 120]})
df[''Data4''] = df[''Data3''].groupby(df[''Date'']).transform(''sum'')
df
Out[74]:
Data2 Data3 Date Sym Data4
0 11 5 2015-05-08 aapl 55
1 8 8 2015-05-07 aapl 108
2 10 6 2015-05-06 aapl 66
3 15 1 2015-05-05 aapl 121
4 110 50 2015-05-08 aaww 55
5 60 100 2015-05-07 aaww 108
6 100 60 2015-05-06 aaww 66
7 40 120 2015-05-05 aaww 121