我有一个看起来像这样的巨大清单(pandas数据框)
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日购买的,则用户ID 11111的有效期至2017年12月31日。在上面的示例列表中,用户12345使用了两次服务,但第二次不应该计数,因为用户12345在2018年1月1日购买了年度会员资格。同样,用户12345在2018年2月1日的活动不应计为新的会员资格购买,因为它是在2017年1月1日购买的。
并且还假定当他们使用第一项服务作为年度会员资格持有人时购买了年度会员资格。(用户ID 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)
您可以尝试分组(按年和用户ID,然后按年和月),但是使用到期日期将需要许多操作。我相信,更具机械性的解决方案可以轻松解决该问题。
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) 2
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句