我有一个很大的清单(熊猫数据),看上去像这样
user userID
Date
1/1/2018 Annual 12345
1/3/2018 Annual 12345
1/5/2018 One Time
1/11/2018 One Time
1/12/2018 One Time
1/13/2018 Annual 98765
.
.
2/1/2018 Annual 12345
2/3/2018 Annual 12345
2/5/2018 One Time
2/11/2018 One Time
2/12/2018 One Time
2/13/2018 Annual 98765这是用户活动的历史记录列表。每次有人使用这个服务,它都会被记录下来。有年度会员持有者和一次用户。
我想做的是计算每月新会员购买的数量。
会员有效期为一年,因此我假设,如果在2017年1月1日购买会员资格,userID 11111将有效期至2017年12月31日。在上面的示例列表中,用户12345使用了该服务两次,但第二次不应该计算在内,因为用户12345在2018年1月1日购买了年度成员资格。同样,2018年2月1日的用户12345 s活动不应被视为新的会员购买,因为它是在2017年1月1日购买的。
此外,人们还假定,年度会员是在他们作为年度会员持有者使用第一次服务时购买的。(userID 12345于2018年1月1日购买了他/她的会员资格。)
编辑
示例
import numpy as np
import pandas as pd
from random import randint
from random import randrange
from datetime import timedelta
from datetime import datetime
start = datetime.strptime('1/1/2017', '%m/%d/%Y')
end = datetime.strptime('12/31/2017', '%m/%d/%Y')
def random_date(start, end):
delta = end - start
int_delta = (delta.days * 24 * 60 * 60) + delta.seconds
random_second = randrange(int_delta)
return start + timedelta(seconds=random_second)
userIDs = []
dates = []
userType = []
for i in range(10000):
userIDs.append( randint(100, 999))
dates.append( random_date(start, end) )
userType.append( randint(1, 2) )
df = pd.DataFrame({'ID': userIDs, 'date':dates, 'type': userType})
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace = True)发布于 2018-01-05 01:32:38
您可以尝试分组(按年份和userID,然后按年份和月份),但是使用到期日期需要很多操作。我相信一个更机械的解决方案可以很简单的解决这个问题。
from dateutil.relativedelta import relativedelta
count = {} # month's number of subscriptions
since = {} # member's date of subscription
for i, r in df[df.type==1].sort_values('date').iterrows():
if r.ID in since and r.date < since[r.ID] + relativedelta(years=1):
continue # valid member, not counting
since[r.ID] = r.date
ym = r.date.year, r.date.month
count[ym] = count.setdefault(ym, 0) + 1我不想把日期作为索引,因为两个成员应该能够同时遵守。
按顺序打印count如下所示:
(2017, 1) 94
(2017, 2) 7
(2018, 1) 76
(2018, 2) 20
(2018, 3) 5
(2019, 1) 50
(2019, 2) 39
(2019, 3) 10
(2019, 4) 2https://stackoverflow.com/questions/48104933
复制相似问题