2017-11-26 1 views
1

Beispieldatenrahmen:Pandas Aggregate nach Monat mit 2 Spalten als Index

Date  | ID | Type 1 | Type 2 | Type 3 
----------------------------------------- 
2017-06-05 | 1 | 2  | 1  | 0 
2017-08-05 | 1 | 0  | 1  | 0 
2017-10-05 | 1 | 2  | 1  | 1 
2017-06-05 | 2 | 0  | 1  | 0 
2017-07-05 | 2 | 2  | 0  | 0 
2017-09-15 | 3 | 0  | 0  | 5 

ich auf monatlicher Basis GROUPBY wollen, so dass jede ID pro Monat bis zur letzten verfügbaren Daten Zeile hat. Zum Beispiel hat ID = 1 in diesem Fall Daten vom 6. bis zum 10. Monat. Also, ID = 1 erhält Zeilen vom 6. bis 10. Monat.

Erwartete Ausgabe für ID = 1:

Date  | ID | Type 1 | Type 2 | Type 3 
----------------------------------------- 
2017-06-05 | 1 | 2  | 1  | 0 
2017-07-05 | 1 | 2  | 1  | 0 
2017-08-05 | 1 | 0  | 1  | 0 
2017-09-05 | 1 | 0  | 1  | 0 
2017-10-05 | 1 | 2  | 1  | 1 

Es beobachtet werden kann, dass die Art Spalten nach oben nicht summieren, sondern die Daten aus der Vergangenheit füllt die Reihe. Wie für Daten in Monat 7 verwendet Monat 6 gleiche Daten.

Below Szenario ist für diese Frage aus -umfang:
Falls die Eingangsdatenrahmen mehrere Zeilen innerhalb selben Monat hat.

Date  | ID | Type 1 | Type 2 | Type 3 
----------------------------------------- 
2017-06-05 | 1 | 2  | 1  | 0 
2017-06-19 | 1 | 0  | 1  | 0 
2017-10-05 | 1 | 2  | 1  | 1 
2017-06-05 | 2 | 0  | 1  | 0 
2017-06-25 | 2 | 2  | 0  | 0 
2017-09-15 | 3 | 0  | 0  | 5 

Wie aggregiert in diesem Fall, dass jeder Monat nur eine einzige Zeile pro ID hat?

Antwort

1

Es ist Hauptproblem hinzufügen Tage, weil Resampling von MS - Anfang des Monats:

df['Date'] = pd.to_datetime(df['Date'], format='%Y%m%d') 
#replace days to 1 
t1 = df['Date'].dt.to_period('m').dt.to_timestamp() 
a = df['Date'] - t1 
#create MultiIndex Series with difference of days from 1's day od month 
s = pd.Series(a.values, index=[df['ID'], t1]) 
print (s) 
ID Date  
1 2017-06-01 4 days 
    2017-08-01 4 days 
    2017-10-01 4 days 
2 2017-06-01 4 days 
    2017-07-01 4 days 
3 2017-09-01 14 days 
dtype: timedelta64[ns] 

#helper df2 for append missing NaNs rows 
df2 = df.set_index(['ID','Date']) 
#add missing dates with resample by start od month and forward fill NaNs 
df1 = df.set_index(['Date']).groupby('ID').resample('MS').ffill() 
print (df1) 
       ID Type 1 Type 2 Type 3 
ID Date         
1 2017-06-01 NaN  NaN  NaN  NaN 
    2017-07-01 1.0  2.0  1.0  0.0 
    2017-08-01 1.0  2.0  1.0  0.0 
    2017-09-01 1.0  0.0  1.0  0.0 
    2017-10-01 1.0  0.0  1.0  0.0 
2 2017-06-01 NaN  NaN  NaN  NaN 
    2017-07-01 2.0  0.0  1.0  0.0 
3 2017-09-01 NaN  NaN  NaN  NaN 

#add missing timedeltas by added rows in df1 by forward filling 
s1 = s.reindex(df1.index, method='ffill') 
print (s1) 
ID Date  
1 2017-06-01 4 days 
    2017-07-01 4 days 
    2017-08-01 4 days 
    2017-09-01 4 days 
    2017-10-01 4 days 
2 2017-06-01 4 days 
    2017-07-01 4 days 
3 2017-09-01 14 days 
dtype: timedelta64[ns] 

#create final MultiIndex with added timedelta by set_index 
mux = [df1.index.get_level_values('ID'), 
     df1.index.get_level_values('Date') + s1.values] 
#add missing NaNs rows with combine original 
df = df1.drop('ID', 1).set_index(mux).combine_first(df2).reset_index() 
print (df) 
    ID  Date Type 1 Type 2 Type 3 
0 1 2017-06-05  2.0  1.0  0.0 
1 1 2017-07-05  2.0  1.0  0.0 
2 1 2017-08-05  2.0  1.0  0.0 
3 1 2017-09-05  0.0  1.0  0.0 
4 1 2017-10-05  0.0  1.0  0.0 
5 2 2017-06-05  0.0  1.0  0.0 
6 2 2017-07-05  0.0  1.0  0.0 
7 3 2017-09-15  0.0  0.0  5.0 

EDIT:

#set days to 1 
df['Date'] = df['Date'] - pd.offsets.MonthBegin() 
#aggregate for unique months 
df1 = df.groupby(['Date','ID']).sum() 
print (df1) 
       Type 1 Type 2 Type 3 
Date  ID       
2017-06-01 1  2  2  0 
      2  2  1  0 
2017-09-01 3  0  0  5 
2017-10-01 1  2  1  1 

#add missing months by resample 
df1 = df1.reset_index(['ID']).groupby('ID').resample('MS').ffill() 
print (df1) 
       ID Type 1 Type 2 Type 3 
ID Date         
1 2017-06-01 1  2  2  0 
    2017-07-01 1  2  2  0 
    2017-08-01 1  2  2  0 
    2017-09-01 1  2  2  0 
    2017-10-01 1  2  1  1 
2 2017-06-01 2  2  1  0 
3 2017-09-01 3  0  0  5 
+0

Können Sie kleine Erklärung liefern. Kommentare in der Seite werden auch in Ordnung sein. @jezrael –

+1

Sicher, gib mir eine Sekunde. – jezrael

+0

'' 's1 = s.reindex (df1.index, methode = 'ffill')' '' throws '' 'Ausnahme: kann nicht mit einem nicht eindeutigen Multiindex umgehen!' '' –

Verwandte Themen