2017-05-05 2 views
7

J'ai une trame de données qui ressemble à ceci:pandas: filtrez le groupe en fonction de plusieurs conditions?

df = pd.DataFrame([ 
    {'id': 123, 'date': '2016-01-01', 'is_local': True }, 
    {'id': 123, 'date': '2017-01-01', 'is_local': False }, 
    {'id': 124, 'date': '2016-01-01', 'is_local': True }, 
    {'id': 124, 'date': '2017-01-01', 'is_local': True } 
]) 
df.date = df.date.astype('datetime64[ns]') 

Je veux obtenir une liste de tous les ID pour lesquels is_local était vrai au début de 2016, mais faux au début de 2017. I » ai commencé par groupe par ID:

gp = df.groupby('id') 

J'ai essayé cela juste pour filtrer la seconde de ces conditions (comme un moyen de commencer), mais il est de retour tous les groupes:

gp.apply(lambda x: ~x.is_local & (x.date > '2016-12-31')) 

Comment puis-je filtrer comme j'ai besoin?

Répondre

7
d1 = df.set_index(['id', 'date']).is_local.unstack() 
d1.index[d1['2016-01-01'] & ~d1['2017-01-01']].tolist() 

[123] 
3

Une autre façon de le faire est par pivoting:

In [24]: ids_by_dates = df.pivot(index='id', columns='date',values='is_local') 

In [25]: ids_by_dates['2016-01-01'] & ~ids_by_dates['2017-01-01'] 
Out[25]: 
id 
123  True 
124 False 
3

Vous pouvez essayer d'utiliser le module datetime bibliothèque datetime et passer plusieurs conditions pour la dataframe

from datetime import datetime 
df = pd.DataFrame([ 
    {'id': 123, 'date': '2016-01-01', 'is_local': True }, 
    {'id': 123, 'date': '2017-01-01', 'is_local': False }, 
    {'id': 124, 'date': '2016-01-01', 'is_local': True }, 
    {'id': 124, 'date': '2017-01-01', 'is_local': True } 
]) 
df.date = df.date.astype('datetime64[ns]') 

Utiliser plusieurs conditions pour découper la trame de données requise

a = df[(df.is_local==True) & (df.date<datetime(2016,12,31) & (df.date>datetime(2015,12,31))] 
b = df[(df.is_local==False) & (df.date<datetime(2017,12,31)) & (df.date>datetime(2016,12,31))] 

Utilisez pandas géants concaténer plus tard

final_df = pd.concat((a,b)) 

volonté sortie vous des lignes 1 et 2

date  id is_local 
2 2016-01-01 124 True 
1 2017-01-01 123 False 

Dans une seule ligne comme suit

final_df = pd.concat((df[(df.is_local==True) & (df.date<datetime(2016,12,31) & (df.date>datetime(2015,12,31))], df[(df.is_local==False) & (df.date<datetime(2017,12,31)) & (df.date>datetime(2016,12,31))])) 
+0

Merci - comment pourrais-je utiliser pour obtenir tous les lignes pour lesquelles 'has_local' est True au début de 2016 et False à 2017? – Richard

+0

Je ne pouvais penser qu'à une solution sale où vous ajoutez plusieurs conditions et les concaténiez ensemble .. Edité ma réponse en conséquence .. – Mechanic

+0

J'ai également édité ma réponse avec une autre condition pour limiter l'année à 2016 et 2017 respectivement – Mechanic