somas mutliple na mesma trama de dados

Paulloed;

Estou tentando executar várias somas na mesma trama de dados e, em seguida, concatenar os novos dataframes em uma trama de dados de final. Existe uma maneira concisa de fazer isso, ou eu preciso usar iteração?

Eu tenho um dicionário desta forma {key: [list_of_idx], ...}e precisa groupby minha trama de dados para cada chave.

Dados de amostra

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)

Input (df)

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

saída esperada (DFF)

     data
grp      
a      30
c       6
b       5

Nota: Eu estou preso com Python 2.7 e pandas 0.16.1

resultado tempo

Eu testei os métodos propostos e calcular o tempo de execução. I mostram o tempo médio per execução (usando 1000 execuções para cada resposta): Eu couln't testar Quang Hoang primeira resposta, por causa da minha versão 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:

Inteligente uso 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: Este magicamente funciona para todas as colunas.
Suponha que temosmore_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')

Então

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

Mas eu ia ficar com mais 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 isso funcione com várias colunas, eu tenho que configurar o defaultdictum pouco 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

Isto é o que ficaria sem defaultdict, mas usando o método setdefaultdo dictobjeto em seu 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

Acho que você gosta

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