Python 计算timeseries数据中连续天数和缺失天数的总数

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

我有一个看起来像这样的数据帧(通常它有很多用户):

我想获得在给定日期之前连续活动和非活动天数的总数。例如,如果日期为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  | 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天。