web-dev-qa-db-fra.com

Pandas - GroupBy puis Fusionner sur la table d'origine

J'essaie d'écrire une fonction pour agréger et effectuer diverses calculs de statistiques sur une trame de données dans Pandas puis la fusionner dans la trame de données d'origine cependant, je suis en cours d'exécution à des problèmes. C'est l'équivalent du code en SQL:

SELECT EID,
       PCODE,
       SUM(PVALUE) AS PVALUE,
       SUM(SQRT(SC*EXP(SC-1))) AS SC,
       SUM(SI) AS SI,
       SUM(EE) AS EE
INTO foo_bar_grp
FROM foo_bar
GROUP BY EID, PCODE 

Et puis rejoignez sur la table d'origine:

SELECT *
FROM foo_bar_grp INNER JOIN 
foo_bar ON foo_bar.EID = foo_bar_grp.EID 
        AND foo_bar.PCODE = foo_bar_grp.PCODE

Voici les étapes: Chargement des données IN: >>

pol_dict = {'PID':[1,1,2,2],
             'EID':[123,123,123,123],
             'PCODE':['GU','GR','GU','GR'],
             'PVALUE':[100,50,150,300],
             'SI':[400,40,140,140],
             'SC':[230,23,213,213],
             'EE':[10000,10000,2000,30000],
             }


pol_df = DataFrame(pol_dict)

pol_df

OUT: >>

   EID    EE PCODE  PID  PVALUE   SC   SI
0  123  10000    GU    1     100  230  400
1  123  10000    GR    1      50   23   40
2  123   2000    GU    2     150  213  140
3  123  30000    GR    2     300  213  140

Étape 2: Calcul et regroupement sur les données:

Mon code pandas est le suivant:

#create aggregation dataframe
poagg_df = pol_df
del poagg_df['PID']
po_grouped_df = poagg_df.groupby(['EID','PCODE'])

#generate acc level aggregate
acc_df = po_grouped_df.agg({
    'PVALUE' : np.sum,
    'SI' : lambda x: np.sqrt(np.sum(x * np.exp(x-1))),
    'SC' : np.sum,
    'EE' : np.sum
})

Cela fonctionne bien jusqu'à ce que je veuille rejoindre sur la table d'origine:

DANS: >>

po_account_df = pd.merge(acc_df, po_df, on=['EID','PCODE'], how='inner',suffixes=('_Acc','_Po'))

OUT: >> KeyError: u'aucun élément nommé EID '

Pour une raison quelconque, la trame de données groupée ne peut pas rejoindre la table d'origine. J'ai cherché des moyens d'essayer de convertir les colonnes groupby en colonnes réelles, mais cela ne semble pas fonctionner.

Veuillez noter que l'objectif final est de pouvoir trouver le pourcentage pour chaque colonne (PVALUE, SI, SC, EE) IE:

pol_acc_df['PVALUE_PCT'] = np.round(pol_acc_df.PVALUE_Po/pol_acc_df.PVALUE_Acc,4)

Merci!

27
WalkingDeadFan

Par défaut, la sortie groupby a les colonnes de regroupement à titre indicatif, pas les colonnes, c'est pourquoi la fusion échoue.

Il existe plusieurs façons de le gérer, la plus simple étant probablement d'utiliser le as_index paramètre lorsque vous définissez l'objet groupby.

po_grouped_df = poagg_df.groupby(['EID','PCODE'], as_index=False)

Ensuite, votre fusion devrait fonctionner comme prévu.

In [356]: pd.merge(acc_df, pol_df, on=['EID','PCODE'], how='inner',suffixes=('_Acc','_Po'))
Out[356]: 
   EID PCODE  SC_Acc  EE_Acc        SI_Acc  PVALUE_Acc  EE_Po  PVALUE_Po  \
0  123    GR     236   40000  1.805222e+31         350  10000         50   
1  123    GR     236   40000  1.805222e+31         350  30000        300   
2  123    GU     443   12000  8.765549e+87         250  10000        100   
3  123    GU     443   12000  8.765549e+87         250   2000        150   

   SC_Po  SI_Po  
0     23     40  
1    213    140  
2    230    400  
3    213    140  
45
chrisb

De la pandas docs :

Transformation: effectuer des calculs spécifiques au groupe et renvoyer un objet indexé comme

Malheureusement, transform fonctionne série par série, vous ne pourrez donc pas exécuter plusieurs fonctions sur plusieurs colonnes comme vous l'avez fait avec agg, mais transform vous permet ignorer merge

po_grouped_df = pol_df.groupby(['EID','PCODE'])
pol_df['sum_pval'] = po_grouped_df['PVALUE'].transform(sum)
pol_df['func_si'] = po_grouped_df['SI'].transform(lambda x: np.sqrt(np.sum(x * np.exp(x-1))))
pol_df['sum_sc'] = po_grouped_df['SC'].transform(sum)
pol_df['sum_ee'] = po_grouped_df['EE'].transform(sum)
pol_df

Résulte en:

PID EID PCODE   PVALUE  SI  SC  EE      sum_pval    func_si         sum_sc  sum_ee
1   123 GU      100     400 230 10000   250         8.765549e+87    443     12000
1   123 GR      50      40  23  10000   350         1.805222e+31    236     40000
2   123 GU      150     140 213 2000    250         8.765549e+87    443     12000
2   123 GR      300     140 213 30000   350         1.805222e+31    236     40000

Pour plus d'informations, consultez this SO answer .

1
vyang