J'essaie de calculer la somme d'un champ pour une période de temps spécifique, après l'application de la fonction de regroupement.

Mon ensemble de données ressemble à ceci:

Date          Company   Country    Sold
01.01.2020       A          BE       1
02.01.2020       A          BE       0
03.01.2020       A          BE       1
03.01.2020       A          BE       1
04.01.2020       A          BE       1
05.01.2020       B          DE       1
06.01.2020       B          DE       0

Je voudrais ajouter une nouvelle colonne pour chaque ligne, qui calcule la somme des Vendus (pour chaque groupe "Entreprise, Pays" pour les 7 derniers jours - sans compter le jour en cours

Date          Company   Country    Sold      LastWeek_Count
01.01.2020       A          BE       1           0
02.01.2020       A          BE       0           1
03.01.2020       A          BE       1           1
03.01.2020       A          BE       1           1
04.01.2020       A          BE       1           3
05.01.2020       B          DE       1           0
06.01.2020       B          DE       0           1

J'ai essayé ce qui suit, mais il inclut également la date actuelle, et il donne des valeurs différentes pour la même date, c'est-à-dire 03.01.2020

df['LastWeek_Count'] = df.groupby(['Company', 'Country']).rolling(7, on ='Date')['Sold'].sum().reset_index()

Existe-t-il une fonction intégrée dans les pandas que je peux utiliser pour effectuer ces calculs?

1
onr 21 août 2020 à 01:54

2 réponses

Meilleure réponse

Une façon serait de d'abord consolider la valeur Vendu de chaque groupe (['Date', 'Entreprise', 'Pays']) sur une seule ligne à l'aide d'un DF temporaire.
Après cela, appliquez votre .groupby avec .rolling avec un intervalle de 8 lignes.
Après avoir calculé la somme, soustrayez la valeur de chaque ligne avec la valeur de la colonne Vendu et ajoutez cette colonne dans le DF d'origine avec .merge

#convert Date column to datetime
df['Date'] = pd.to_datetime(df['Date'], format='%d.%m.%Y')
#create a temporary DataFrame
df2 = df.groupby(['Date', 'Company', 'Country'])['Sold'].sum().reset_index()
#calc the lastweek
df2['LastWeek_Count'] = (df2.groupby(['Company', 'Country'])
                            .rolling(8, min_periods=1, on = 'Date')['Sold']
                            .sum().reset_index(drop=True)
                        ) 
#subtract the value of 'lastweek' from the current 'Sold'
df2['LastWeek_Count'] = df2['LastWeek_Count'] - df2['Sold']
#add th2 new column in the original DF
df.merge(df2.drop(columns=['Sold']), on = ['Date', 'Company', 'Country'])
#output:
    Date        Company Country Sold    LastWeek_Count
0   2020-01-01  A       BE      1       0.0
1   2020-01-02  A       BE      0       1.0
2   2020-01-03  A       BE      1       1.0
3   2020-01-03  A       BE      1       1.0
4   2020-01-04  A       BE      1       3.0
5   2020-01-05  B       DE      1       0.0
6   2020-01-06  B       DE      0       1.0
0
Terry 21 août 2020 à 02:27

Vous pouvez utiliser une fenêtre .rolling de 8, puis soustraire la somme de la date (pour chaque ligne groupée) pour obtenir efficacement les 7 jours précédents. Pour cet exemple de données, nous devons également transmettre min_periods=1 (sinon vous obtiendrez des valeurs NaN, mais pour votre ensemble de données réel, vous devrez décider ce que vous voulez faire avec les fenêtres qui sont <{{X4 }}).

Ensuite, à partir de la fenêtre .rolling de 8, faites simplement un autre .groupby des colonnes pertinentes mais incluez également Date cette fois, et prenez la valeur max du colonne LastWeek_Count nouvellement créée. Vous devez prendre le max, car vous avez plusieurs enregistrements par jour, donc en prenant le maximum, vous prenez le montant total agrégé par Date.

Ensuite, créez une série qui prend le groupé par sum par Date. Dans la dernière étape, soustrayez la somme par date du maximum de 8 jours glissants, ce qui est une solution de contournement pour obtenir la somme des 7 jours précédents, car il n'y a pas de paramètre pour un décalage avec .rolling:

df['Date'] = pd.to_datetime(df['Date'], dayfirst=True)
df['LastWeek_Count'] = df.groupby(['Company', 'Country']).rolling(8, min_periods=1, on='Date')['Sold'].sum().reset_index()['Sold']
df['LastWeek_Count'] = df.groupby(['Company', 'Country', 'Date'])['LastWeek_Count'].transform('max')
s = df.groupby(['Company', 'Country', 'Date'])['Sold'].transform('sum')
df['LastWeek_Count'] = (df['LastWeek_Count']-s).astype(int)

Out[17]: 
        Date Company Country  Sold  LastWeek_Count
0 2020-01-01       A      BE     1               0
1 2020-01-02       A      BE     0               1
2 2020-01-03       A      BE     1               1
3 2020-01-03       A      BE     1               1
4 2020-01-04       A      BE     1               3
5 2020-01-05       B      DE     1               0
6 2020-01-06       B      DE     0               1
1
David Erickson 21 août 2020 à 00:10