Python 计算timeseries数据中连续天数和缺失天数的总数
我有一个看起来像这样的数据帧(通常它有很多用户): 我想获得在给定日期之前连续活动和非活动天数的总数。例如,如果日期为2015-01-23,则:Python 计算timeseries数据中连续天数和缺失天数的总数,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个看起来像这样的数据帧(通常它有很多用户): 我想获得在给定日期之前连续活动和非活动天数的总数。例如,如果日期为2015-01-23,则: userid | days_active_jb | days_inactive_jb | ttl_days_active | ttl_days_inactive 222 | 3 | 2 | 10 | 2 userid | days_active_jb | d
userid | days_active_jb | days_inactive_jb | ttl_days_active | ttl_days_inactive
222 | 3 | 2 | 10 | 2
userid | days_active_jb | days_inactive_jb | ttl_days_active | ttl_days_inactive
222 | 2 | 0 | 5 | 1
或者,如果给定日期为2015-01-15,则:
userid | days_active_jb | days_inactive_jb | ttl_days_active | ttl_days_inactive
222 | 3 | 2 | 10 | 2
userid | days_active_jb | days_inactive_jb | ttl_days_active | ttl_days_inactive
222 | 2 | 0 | 5 | 1
我有大约300000行要处理以获得最终的数据帧。我想知道实现这一目标的有效方法是什么。有什么想法吗
以下是各栏的说明:
days\u active\u jb
:学生在给定日期之前连续进行活动的天数
days\u inactive\u jb
:学生在给定日期之前连续无活动的天数
ttl\u days\u active
:学生在给定日期前任何一天进行活动的天数
ttl\u days\u inactive
:学生在给定日期前任何一天没有活动的天数。设置:
df
Out[1714]:
userid activityday
0 222 2015-01-09 12:00:00
1 222 2015-01-10 12:00:00
2 222 2015-01-11 12:00:00
3 222 2015-01-13 12:00:00
4 222 2015-01-14 12:00:00
5 222 2015-01-15 12:00:00
6 222 2015-01-17 12:00:00
7 222 2015-01-18 12:00:00
8 222 2015-01-19 12:00:00
9 222 2015-01-20 12:00:00
11 322 2015-01-09 12:00:00
12 322 2015-01-10 12:00:00
13 322 2015-01-11 12:00:00
14 322 2015-01-13 12:00:00
15 322 2015-01-14 12:00:00
16 322 2015-01-15 12:00:00
17 322 2015-01-17 12:00:00
18 322 2015-01-18 12:00:00
19 322 2015-01-19 12:00:00
20 322 2015-01-20 12:00:00
解决方案
def days_active_jb(x):
x = x[x<pd.to_datetime(cut_off_days)]
if len(x) == 0:
return 0
x = [e.date() for e in x.sort_values(ascending=False)]
prev = x.pop(0)
i = 1
for e in x:
if (prev-e).days == 1:
i+=1
prev = e
else:
break
return i
def days_inactive_jb(x):
diff = (pd.to_datetime(cut_off_days) -max(x)).days
return 0 if diff<0 else diff
def ttl_days_active(x):
x = x[x<pd.to_datetime(cut_off_days)]
return len(x[x<pd.to_datetime(cut_off_days)])
def ttl_days_inactive(x):
#counter the missing days between start and end dates
x = x[x<pd.to_datetime(cut_off_days)]
return len(pd.date_range(min(x),max(x))) - len(x)
#drop duplicate userid-activityday pairs
df = df.drop_duplicates(subset=['userid','activityday'])
cut_off_days = '2015-01-23'
df.sort_values(by=['userid','activityday'],ascending=False).\
groupby('userid')['activityday'].\
agg([days_active_jb,
days_inactive_jb,
ttl_days_active,
ttl_days_inactive]).\
astype(np.int64)
Out[1856]:
days_active_jb days_inactive_jb ttl_days_active ttl_days_inactive
userid
222 4 2 10 2
322 4 2 10 2
cut_off_days = '2015-01-15'
df.sort_values(by=['userid','activityday'],ascending=False).\
groupby('userid')['activityday'].\
agg([days_active_jb,
days_inactive_jb,
ttl_days_active,
ttl_days_inactive]).\
astype(np.int64)
Out[1863]:
days_active_jb days_inactive_jb ttl_days_active ttl_days_inactive
userid
222 2 0 5 1
322 2 0 5 1
def活动天数jb(x):
x=x[x“”
此代码适用于同一文件上的不同用户id
数据应严格按照您提供的格式呈现
'''
导入日期时间
'''
下面的列表理解生成列表的列表
不同uid的文件中的[uid,activedate,time]
'''
data=[item.strip()中的item 2为[item.split()中的item 2为[data for data\
处于打开状态('c:/python34/stack.txt')。如果项目2]
data.pop(0)##弹出第一个元素即标题
def活动日期(活动列表,uid):
''返回活动日期的年、月和日的列表
对于作为“uid”的给定用户id
对于活动列表中的项目:
项目.pop(2)#移除时间
对于项目3中的项目4返回[[eval(item4.lstrip('0'))]
[item2.数据中项目的[item[1]中项目2的拆分('-'),如果\
项目[0]==uid]]
def活动天数(从年月日至年月日):
#返回从“开始日期”到“截止日期”的活动天数
#“到”
计数=0
对于日期中的项目:
d1=日期时间。日期(项目[0]、项目[1]、项目[2])
如果d1>来自u和d1 0:
如果lst[i]==lst[i-1]:
一级pop(一)
i-=1
返回lst
活动=删除重复项(活动日期(数据,'222'))#将uid变量作为字符串传递
from=日期时间日期(2015,1,1)
to=日期时间日期(2015,1,26)
活动日=活动日(从活动日到活动日)
总天数=从_
非活动天数=总天数。天数-活动天数
打印('活动天数:%s和非活动天数:%s'(活动天数,非活动天数))
days\u active\u jb和days\u inactive\u jb是如何定义的?如果days\u inactive\u jb是多1天的间隔数,第二个示例是否应该有1个for days\u inactive\u jb?@Allen感谢您的回答。我提供了解释。我将很快尝试您的解决方案,并会让您知道。我对给定日期之前的连续活动天数感兴趣。例如,如果学生在给定日期前的最后3天内只有活动,则返回值应为3。不关心他们在5天前是否有活动等。您认为days\u active\u jb(x):
检查是否存在此问题?@renakre,我已更新了代码。如果截止日期为2015-01-23,则活动天数应为4天,因为从“2015-01-17”到“2015-01-20”是4天。