2016-11-27 5 views
4

У меня есть dataframe «ф.р.», который выглядит следующим образом:Python Панды Dataframe GroupBy Размер, основанный на состоянии

id date1 date2 
1 11/1/2016 11/1/2016 
1 11/1/2016 11/2/2016 
1 11/1/2016 11/1/2016 
1 11/1/2016 11/2/2016 
1 11/2/2016 11/2/2016 
2 11/1/2016 11/1/2016 
2 11/1/2016 11/2/2016 
2 11/1/2016 11/1/2016 
2 11/2/2016 11/2/2016 
2 11/2/2016 11/2/2016 

То, что я хотел бы сделать, это GroupBy идентификатор, а затем получить размер для каждого идентификатора где date1 = date2. Результат должен выглядеть следующим образом:

id samedate count 
1 11/1/2016 2 
1 11/2/2016 1 
2 11/1/2016 2 
2 11/2/2016 2 

Я попытался это:

gb=df.groupby(id').apply(lambda x: x[x.date1== x.date2]['date1'].size()) 

И получить эту ошибку:

TypeError: 'int' object is not callable 

Вы можете, конечно, флаг каждый экземпляр где date1 и date2 равны , затем подсчитайте эти флаги для каждого идентификатора по каждому образцу, но я должен поверить, что для этого есть опция groupby.

ответ

4

Вы можете использовать boolean indexing первый и затем агрегированные size:

df.date1 = pd.to_datetime(df.date1) 
df.date2 = pd.to_datetime(df.date2) 

df = df[df.date1 == df.date2] 
gb=df.groupby(['id', 'date1']).size().reset_index(name='count') 
print (gb) 
    id  date1 count 
0 1 2016-11-01  2 
1 1 2016-11-02  1 
2 2 2016-11-01  2 
3 2 2016-11-02  2 

Настройка времени:

In [79]: %timeit (df[df.date1 == df.date2].groupby(['id', 'date1']).size().reset_index(name='count')) 
100 loops, best of 3: 3.84 ms per loop 

In [80]: %timeit (df.groupby(['id', 'date1']).apply(lambda x: (x['date1'] == x['date2']).sum()).reset_index()) 
100 loops, best of 3: 7.57 ms per loop 

Код для таймингов:

#len df = 10k 
df = pd.concat([df]*1000).reset_index(drop=True) 
#print (df) 

df.date1 = pd.to_datetime(df.date1) 
df.date2 = pd.to_datetime(df.date2) 
+0

Спасибо за таймингов. Это лучший способ сделать это. – Zero

+0

Спасибо за ответ, первая идея была очень похожа на ваш ответ. – jezrael

+0

Спасибо. Отлично! – clg4

3

Вам необходимо сгруппировать по две колонки, а затем применить, чтобы проверить, если date1 равен date2

In [105]: df.groupby(['id', 'date1']).apply(lambda x: (x['date1'] == x['date2']).sum()) 
Out[105]: 
id date1 
1 11/1/2016 2 
    11/2/2016 1 
2 11/1/2016 2 
    11/2/2016 2 
dtype: int64 
+0

Вы собираетесь быть медленнее, чем jezrael, если применить функцию лямбда против всего набора, и если вы делаете логическое сравнение внутри лямбда-функции. – Boud

+0

спасибо за ответ. ! – clg4