Comment réduire également la valeur après le regroupement?

voix
2

Je table dans laquelle certaines valeurs appartiennent à l' index et une autre appartiens à des valeurs répétées. Dans l' exemple sidest l' indice, les coûts beolng à sid, mais sid peut contenir de nombreuses transactions et encore plus une transaction peut contenir plusieurs catégories.

df = pd.DataFrame([
    [1, 100, 1, 'A', 1, 50, 2],
    [1, 100, 2, 'A', 1, 50, 1],
    [1, 100, 2, 'B', 2, 100, 1],
    [1, 100, 2, 'C', 3, 50, 1],
    [2, 200, 3, 'D', 4, 500, 1],
    [2, 200, 4, 'C', 2, 100, 1],
    [3, 200, 5, 'B', 2, 100, 1],
    [3, 200, 5, 'A', 1, 50, 1],
    [3, 200, 5, 'A', 3, 50, 1]
], columns=['sid', 'costs', 'transaction_id', 'category', 'sku', 'price', 'quantity'])

df['revenue'] = df['price'] * df['quantity']

Donc, si le regard niveau sid je dois prendre la première valeur des coûts et la somme des revenus. Voici comment cela devrait ressembler. Les coûts totaux - 500, les recettes totales - 1100.

df.groupby('sid').agg({'costs': 'min', 'revenue':'sum'}).pivot_table(index='sid', margins=True, aggfunc='sum')  

entrez

Mais je veux décomposer sid par catégorie. Je peux le faire de cette façon.

df.groupby(['sid', 'category']).agg({'costs': 'min', 'revenue':'sum'}).pivot_table(index=['sid', 'category'], aggfunc='sum', margins=True)

entrez

Mon problème est que pour tous les coûts de ligne ont été dupliqués. Et somme des coûts est 1100 ce qui est faux. Je veux réduire les coûts tout aussi en ce qui concerne à la quantité de catégories dans chaque sid. Donc, il va ressemble

entrez

Est-il possible d'appliquer cette fonction de roulement?

Créé 18/12/2018 à 11:02
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
2

Je pense que vous devez diviser le nombre de sidpar groupes créés par transformet size:

df = df.groupby(['sid', 'category']).agg({'costs': 'min', 'revenue':'sum'})
df['costs'] = df['costs'].div(df.groupby('sid')['costs'].transform('size'))
df = df.pivot_table(index=['sid', 'category'], aggfunc='sum', margins=True)
print (df)
                   costs  revenue
sid category                     
1   A          33.333333      150
    B          33.333333      100
    C          33.333333       50
2   C         100.000000      100
    D         100.000000      500
3   A         100.000000      100
    B         100.000000      100
All           500.000000     1100
Créé 18/12/2018 à 11:32
source utilisateur

voix
3

Voici quelque chose que vous pourriez faire:

g = df.groupby(['sid', 'category']).agg({'revenue':'sum', 'costs': 'min'})
div = df.groupby(['sid'])['category'].nunique()
g['costs'] = g['costs']/div

                revenue     costs
sid category                     
1   A             150   33.333333
    B             100   33.333333
    C              50   33.333333
2   C             100  100.000000
    D             500  100.000000
3   A             100  100.000000
    B             100  100.000000

Et pour la dernière ligne, y compris sumdes deux colonnes il suffit d' ajouter à nouveau à la fin:

g.pivot_table(index=['sid', 'category'], aggfunc='sum', margins=True)
Créé 18/12/2018 à 11:33
source utilisateur

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more