Python 在groupby中计算具有连续日期的行
假设我的数据框看起来像这样:Python 在groupby中计算具有连续日期的行,python,pandas,dataframe,Python,Pandas,Dataframe,假设我的数据框看起来像这样: d = {'item_number':['K208UL','AKD098008','DF900A','K208UL','AKD098008'] 'Comp_ID':['998798098','988797387','12398787','998798098','988797387'] 'date':['2016-11-12','2016-11-13','2016-11-17','2016-11-13','2016-11-14']} df = p
d = {'item_number':['K208UL','AKD098008','DF900A','K208UL','AKD098008']
'Comp_ID':['998798098','988797387','12398787','998798098','988797387']
'date':['2016-11-12','2016-11-13','2016-11-17','2016-11-13','2016-11-14']}
df = pd.DataFrame(data=d)
我想计算连续几天观察到相同项目编号
和Comp\u ID
的次数
我想这看起来会像是:
g = df.groupby(['Comp_ID','item_number'])
g.apply(lambda x: x.loc[x.iloc[i,'date'].shift(-1) - x.iloc[i,'date'] == 1].count())
然而,在比较之前,我需要从每个日期中提取日期作为int,这也是我遇到的问题
for i in df.index:
wbc_seven.iloc[i, 'day_column'] = datetime.datetime.strptime(df.iloc[i,'date'],'%Y-%m-%d').day
显然,基于位置的索引只允许整数?如何解决此问题?一种解决方案是使用数据透视表来计算连续几天观察到的
Comp\u ID
和item\u number
的次数
import pandas as pd
d = {'item_number':['K208UL','AKD098008','DF900A','K208UL','AKD098008'],'Comp_ID':['998798098','988797387','12398787','998798098','988797387'],'date':['2016-11-12','2016-11-13','2016-11-17','2016-11-13','2016-11-14']}
df = pd.DataFrame(data=d).sort_values(['item_number','Comp_ID'])
df['date'] = pd.to_datetime(df['date'])
df['delta'] = (df['date'] - df['date'].shift(1))
df = df[(df['delta']=='1 days 00:00:00.000000000') & (df['Comp_ID'] == df['Comp_ID'].shift(1)) &
(df['item_number'] == df['item_number'].shift(1))].pivot_table( index=['item_number','Comp_ID'],
values=['date'],aggfunc='count').reset_index()
df.rename(columns={'date':'consecutive_days'},inplace =True)
导致
item_number Comp_ID consecutive_days
0 AKD098008 988797387 1
1 K208UL 998798098 1
但是,我需要从每个日期中提取日期作为int
在比较之前,我也有问题
为什么?
要修复代码,您需要:
consecutive['date'] = pd.to_datetime(consecutive['date'])
g = consecutive.groupby(['Comp_ID','item_number'])
g['date'].apply(lambda x: sum(abs((x.shift(-1) - x)) == pd.to_timedelta(1, unit='D')))
注意以下几点:
timedelta
,以便进行适当的比较提示:为您的工作编写顶级函数,而不是
lambda
,因为它符合更好的可读性、简洁性和美观性:
def differencer(grp, day_dif):
"""Counts rows in grp separated by day_dif day(s)"""
d = abs(grp.shift(-1) - grp)
return sum(d == pd.to_timedelta(day_dif, unit='D'))
g['date'].apply(differencer, day_dif=1)
说明:
这很简单。然后减去日期。差异将导致a,它还需要与
timedelta
对象进行比较,因此将1(或day_dif
)转换为timedelta
。该转换的结果将是布尔级数。布尔值表示为0表示False
,1表示True
。布尔数列之和将返回该数列中True
值的总数。我遇到了以下错误:TypeError:-:“str”和“str”的操作数类型不受支持。显然,您需要将“date”列转换为Timestamp
类型。分组前使用此连续['date']=pd.to_datetime(连续['date'])
。我也会编辑答案。太棒了!从我的第一轮QA来看,它看起来工作得很好。我并没有想象的那么远。如果您能就代码中发生的事情添加一些解释,我将不胜感激@卡尔蒂基补充了一个解释。另外,稍微简化一下,您不需要使用比较返回的布尔序列再次建立索引。一个简单的sum
就足够了。你肯定离得不远了,干得好:-)。请接受答案,若你们觉得有用,请投票表决。那些控件在答案的左边。我还没有投票的代表点数,但def正是我想要的!