2017-10-19 16 views
2

Je cherche à regrouper par deux colonnes: user_id et date; cependant, si les dates sont assez proches, je veux pouvoir considérer les deux entrées faisant partie du même groupe et du même groupe en conséquence. La date est m-d-yGroupe Pandas Par plage de dates

user_id  date  val 
1   1-1-17  1 
2   1-1-17  1 
3   1-1-17  1 
1   1-1-17  1 
1   1-2-17  1 
2   1-2-17  1 
2   1-10-17 1 
3   2-1-17  1 

Le groupe regrouperait par user_id et dates +/- 3 jours à l'autre. de sorte que le groupe en additionnant val ressemblerait à ceci:

user_id  date  sum(val) 
1   1-2-17  3 
2   1-2-17  2 
2   1-10-17 1 
3   1-1-17  1 
3   2-1-17  1 

Toute personne façon pouvait penser que cela pourrait être fait (un peu) facilement? Je sais qu'il y a des aspects problématiques de cela. par exemple, que faire si les dates s'enchaînent sans cesse à trois jours d'intervalle? mais les données exactes en utilisant seulement a 2 valeurs par personne.

Merci!

Répondre

5

Je convertir en une colonne datetime puis utilisez pd.TimeGrouper:

dates = pd.to_datetime(df.date, format='%m-%d-%y') 
print(dates) 
0 2017-01-01 
1 2017-01-01 
2 2017-01-01 
3 2017-01-01 
4 2017-01-02 
5 2017-01-02 
6 2017-01-10 
7 2017-02-01 
Name: date, dtype: datetime64[ns] 

df = df.assign(date=dates).set_index('date')\ 
      .groupby(['user_id', pd.TimeGrouper('3D')]).sum().reset_index()  
print(df) 
    user_id  date val 
0  1 2017-01-01 3 
1  2 2017-01-01 2 
2  2 2017-01-10 1 
3  3 2017-01-01 1 
4  3 2017-01-31 1 

solution similaire en utilisant pd.Grouper:

df = df.assign(date=dates).groupby(['user_id', 
     pd.Grouper(key='date', freq='3D')]).sum().reset_index() 
print(df) 
    user_id  date val 
0  1 2017-01-01 3 
1  2 2017-01-01 2 
2  2 2017-01-10 1 
3  3 2017-01-01 1 
4  3 2017-01-31 1 

Mise à jour: TimeGrouper seront dépréciés dans les futures versions de pandas, donc Grouper serait préféré dans ce scénario (merci pour les heads up, Vaishali!).

+1

J'ai toujours peur de toucher tout moment question relative ... LOL BTW +1 – Wen

+1

incroyable, le mérou jamais utilisé en quelque sorte – Vaishali

+0

'Grouper' est 'TimeGrouper' – Wen

0

Je viens avec une solution très laid, mais fonctionne toujours ...

df=df.sort_values(['user_id','date']) 
df['Key']=df.sort_values(['user_id','date']).groupby('user_id')['date'].diff().dt.days.lt(3).ne(True).cumsum() 
df.groupby(['user_id','Key'],as_index=False).agg({'val':'sum','date':'first'}) 

Out[586]: 
    user_id Key val  date 
0  1 1 3 2017-01-01 
1  2 2 2 2017-01-01 
2  2 3 1 2017-01-10 
3  3 4 1 2017-01-01 
4  3 5 1 2017-02-01