我有一个包含用户订阅服务的表。
当用户状态发生变化时,表格中会插入一个新行,其中包含相同的user_id,更新的新时间和新状态。
示例表:
example = {'updated_at':['2017-01-01', '2017-01-01', '2017-01-02','2017-01-02', '2017-01-03','2017-01-03','2017-01-03','2017-01-04','2017-01-04'],
'user_id': [9, 10, 11, 12, 13, 12, 14, 11, 10],
'status': ['trial', 'cancelled', 'trial', 'trial', 'trial', 'active', 'active', 'active', 'active']}
example_data = pd.DataFrame.from_dict(example)
我正在尝试构建的是一个表格,显示按日期状态分组的用户数。如果从一天到另一天没有变化,那么表格应该在两天都显示相同的数据。
如果其中一个用户更新了其状态,那么从那一天开始,这些列应反映新的状态细分。
期望的结果示例:
print desired_results
date n status
0 2017-01-01 0 active
1 2017-01-01 1 cancelled
2 2017-01-01 1 trial
3 2017-01-02 0 active
4 2017-01-02 1 cancelled
5 2017-01-02 3 trial
6 2017-01-03 2 active
7 2017-01-03 1 cancelled
8 2017-01-03 4 trial
9 2017-01-04 4 active
10 2017-01-04 0 cancelled
11 2017-01-04 2 trial
到目前为止我尝试过:
(example_data.
groupby(['updated_at','status']). #group by date and status
count(). # count in each group
unstack(fill_value = 0). # unstack
cumsum(). # cumsum for each status
stack(). # stack all together again
reset_index().rename(columns={'user_id': 'n'})) # rename column and reindex
但这并没有给我我希望的东西。问题是我将更新计为新记录,因此用户被重复计算。
任何人都可以帮忙吗?
答案 0 :(得分:0)
我不确定你想要什么,但似乎这会起作用?
(example_data.
groupby(['updated_at','status']). #group by date and status
count(). # count in each group
unstack(fill_value = 0). # unstack
stack(). # stack all together again
reset_index().rename(columns={'user_id': 'n'})) # rename column and reindex
答案 1 :(得分:0)
我意识到我实际上必须做的只是“继续”#39;每个日期的每个用户的先前观察结果,然后只做一个简单的groupby并计算。
我在SO上发现了这个answer关于如何在Groupby中重新索引日期,这让我走上了正确的轨道。
我的解决方案如下:
def reindex_by_date(df):
dates = ['2017-01-01','2017-01-02','2017-01-03','2017-01-04']
return df.reindex(dates, method = 'ffill')
(example_data.
groupby('user_id').
apply(reindex_by_date).
reset_index(0, drop=True).
reset_index().
groupby(['status', 'index']).
count().
reset_index().
sort_values(['index','status']).
rename(columns={'index':'date'})
)
上述内容似乎有点多余,可能有更简洁的方法。