sumas Mutliple en la misma trama de datos

Paulloed;

Estoy tratando de realizar múltiples sumas en la misma trama de datos y luego concatenar las nuevas tramas de datos en una sola trama de datos final. ¿Hay una manera concisa de hacer esto, o tengo que usar iteración?

Tengo un diccionario de esta forma {key: [list_of_idx], ...}y la necesidad de GroupBy mi trama de datos para cada tecla.

Data de muestra

import random
random.seed(1)

df_len = 5
df = {'idx':{i: i+1 for i in range(df_len)}, 'data':{i:random.randint(1,11) for i in range(df_len)}}
df = pd.DataFrame(df).set_index('idx')

# Groups with the idx to groupby
groups = {'a': [1,2,3,4,5],
          'b': [1,4],
          'c': [5]}

# I'm trying to avoid/find a faster way than this
dfs = []
for grp in groups:
    _df = df.loc[groups[grp]]
    _df['grp'] = grp
    _df = _df.groupby('grp').sum()

    dfs.append(_df)
dff = pd.concat(dfs)

Entrada (df)

   data  idx
0     2    1
1    10    2
2     9    3
3     3    4
4     6    5

Resultados previstos (DFF)

     data
grp      
a      30
c       6
b       5

Nota: estoy atascado con Python 2.7 y 0.16.1 pandas

resultado tiempo

Probé los métodos propuestos y calcular el tiempo de ejecución. Muestro el tiempo medio por cada ejecución (1000 utilizando ejecuciones por cada respuesta): Yo Couln't probar Quang Hoang primera respuesta, debido a mi versión de los pandas.

time         method  
0.00696 sec  my method (question)  
0.00328 sec  piRSquared (pd.concat)  
0.00024 sec  piRSquared (collections and defaultdict)  
0.00444 sec  Quang Hoang (2nd method : concat + reindex)  
piRSquared:

El uso inteligente de pd.concat

pd.concat({k: df.loc[v] for k, v in groups.items()}).sum(level=0)

   data
a    22
b     8
c     2

NOTA: Esto funciona mágicamente para todas las columnas.
Supongamos que tenemosmore_data

import random
random.seed(1)
df_len = 5
df = {
    'idx':{i: i+1 for i in range(df_len)},
    'data':{i:random.randint(1,11) for i in range(df_len)},
    'more_data':{i:random.randint(1,11) for i in range(df_len)},
}
df = pd.DataFrame(df).set_index('idx')

Luego

pd.concat({k: df.loc[v] for k, v in groups.items()}).sum(level=0)

   data  more_data
a    22         42
b     8         19
c     2          7

Pero me quedo con más de Python: collections.defaultdict

from collections import defaultdict

results = defaultdict(int)

for k, V in groups.items():
    for v in V:
        results[k] += df.at[v, 'data']

pd.Series(results)

a    22
b     8
c     2
dtype: int64

Para que esto funcione con múltiples columnas, tengo que configurar el defaultdictun poco diferente:

from collections import defaultdict

results = defaultdict(lambda: defaultdict(int))

for k, V in groups.items():
    for v in V:
        for c in df.columns:
            results[c][k] += df.at[v, c]

pd.DataFrame(results)

   data  more_data
a    22         42
b     8         19
c     2          7

Esto es lo que se vería como sin defaultdictpero utilizando el método setdefaultdel dictobjeto en su lugar.

results = {}

for k, V in groups.items():
    for v in V:
        for c in df.columns:
            results.setdefault(c, {})
            results[c].setdefault(k, 0)
            results[c][k] += df.at[v, c]

pd.DataFrame(results)

   data  more_data
a    22         42
b     8         19
c     2          7

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=294456&siteId=1
Recomendado
Clasificación