Quiero agregar algunas columnas para las características del grupo (std, mean ...), el siguiente código funciona pero el conjunto de datos es realmente grande y el rendimiento es malo. ¿Hay alguna buena idea para mejorar el código? Gracias

import pandas as pd

df = pd.DataFrame([[1,2,1], [1,2,2], [1,3,3], [1,3,4],[2,8,9], [2,11,11]], columns=['A', 'B', 'C'])
df['mean'] = 0

df2 = df.groupby('A')
for a, group in df2:
    mean = group['C'].mean()
    df.loc[df['A'] == a, 'mean'] = mean

df
'''
     A   B   C  mean
0   1   2   1   2.5
1   1   2   2   2.5
2   1   3   3   2.5
3   1   3   4   2.5
4   2   8   9   10.0
5   2   11  11  10.0
'''
1
Sai Li 2 mar. 2018 a las 04:33

3 respuestas

La mejor respuesta

Pandas ' groupby.transform hace el trabajo de transmitir estadísticas agregadas a través del índice original. Esto lo hace perfecto para sus propósitos y debe considerarse la forma idiomática de realizar esta tarea.

Solución canalizada que produce una copia de df con una nueva columna

df.assign(Mean=df.groupby('A').C.transform('mean'))

   A   B   C  Mean
0  1   2   1   2.5
1  1   2   2   2.5
2  1   3   3   2.5
3  1   3   4   2.5
4  2   8   9  10.0
5  2  11  11  10.0

Asignación en el lugar

df['Mean'] = df.groupby('A').C.transform('mean')
df

   A   B   C  Mean
0  1   2   1   2.5
1  1   2   2   2.5
2  1   3   3   2.5
3  1   3   4   2.5
4  2   8   9  10.0
5  2  11  11  10.0

Alternativamente, puede usar pd.factorize y np.bincount

f, u = pd.factorize(df.A.values)
totals = np.bincount(f, df.C.values)
counts = np.bincount(f)
df.assign(Mean=(totals / counts)[f])

   A   B   C  Mean
0  1   2   1   2.5
1  1   2   2   2.5
2  1   3   3   2.5
3  1   3   4   2.5
4  2   8   9  10.0
5  2  11  11  10.0
5
piRSquared 2 mar. 2018 a las 01:50

Puedes llamar a mean con índice

df.assign(mean=df.A.map(df.set_index('A').C.mean(level=0)))
Out[28]: 
   A   B   C  mean
0  1   2   1   2.5
1  1   2   2   2.5
2  1   3   3   2.5
3  1   3   4   2.5
4  2   8   9  10.0
5  2  11  11  10.0

O usando get

df['mean']=df.set_index('A').C.mean(level=0).get(df.A).values
df
Out[35]: 
   A   B   C  mean
0  1   2   1   2.5
1  1   2   2   2.5
2  1   3   3   2.5
3  1   3   4   2.5
4  2   8   9  10.0
5  2  11  11  10.0
2
YOBEN_S 2 mar. 2018 a las 01:48

Aquí hay una manera:

s = df.groupby('A')['C'].mean()

df['mean'] = df['A'].map(s)

#    A   B   C  mean
# 0  1   2   1   2.5
# 1  1   2   2   2.5
# 2  1   3   3   2.5
# 3  1   3   4   2.5
# 4  2   8   9  10.0
# 5  2  11  11  10.0

Explicación

  • Primero, groupby 'A' y calcule mean de 'C'. Esto crea una serie con entradas únicas de índice en 'A' y valores según sea necesario.
  • En segundo lugar, map esta serie en su marco de datos. Esto es posible porque pd.Series.map puede tomar una serie como entrada.
3
jpp 2 mar. 2018 a las 01:36