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!
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
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 .