我正试图在pandas
中完成一项队列分析。我希望能够在用户注册时查看第1个月,第2个月,第n个月和用户的活动。您可以使用groupby
来完成此操作,但如果用户在特定月份内处于非活动状态,则它们实际上不会显示在该月的数据中。
理想情况下,这是我正在尝试构建的dataframe
:
| UserID | SignUpDate | VisitMonth | Visits |
|--------|------------|------------|--------|
| 1 | 2014-03 | 2014-03 | 2 |
| 1 | 2014-03 | 2014-04 | 1 |
| 1 | 2014-03 | 2014-05 | 0 |
| 1 | 2014-03 | 2014-06 | 0 |
| 1 | 2014-03 | 2014-07 | 0 |
| 1 | 2014-03 | 2014-08 | 0 |
| 1 | 2014-03 | 2014-09 | 0 |
| 1 | 2014-03 | 2014-10 | 1 |
| 1 | 2014-03 | 2014-11 | 0 |
| 1 | 2014-03 | 2014-12 | 0 |
| 1 | 2014-03 | 2015-01 | 2 |
| 1 | 2014-03 | 2015-02 | 1 |
| 1 | 2014-03 | 2015-03 | 0 |
| 2 | 2015-01 | 2015-01 | 2 |
| 2 | 2015-01 | 2015-02 | 0 |
| 2 | 2015-01 | 2015-03 | 2 |
#Sample of users
users = [{'UserID': 'U1', 'SignUpDate': '2014-03-15'}, {'UserID': 'U2', 'SignUpDate': '2015-01-10'}]
#Create dataframe with users
usersDF = pd.DataFrame(data=users)
#Convert SignUpDate from Object to date
usersDF['SignUpDate'] = pd.to_datetime(usersDF['SignUpDate'])
#Add new column to build the month-only
usersDF['SignUpMonth'] = usersDF['SignUpDate'].dt.to_period('M')
#Sample of visits
visits =[{'UserID': 'U1', 'VisitDate': '2014-03-15'}, {'UserID': 'U1', 'VisitDate': '2014-03-28'}, {'UserID': 'U1', 'VisitDate': '2014-04-10'}, {'UserID': 'U1', 'VisitDate': '2014-10-28'}, {'UserID': 'U1', 'VisitDate': '2015-01-02'}, {'UserID': 'U2', 'VisitDate': '2015-01-10'}, {'UserID': 'U2', 'VisitDate': '2015-01-11'}, {'UserID': 'U1', 'VisitDate': '2014-01-20'}, {'UserID': 'U1', 'VisitDate': '2014-02-15'}, {'UserID': 'U2', 'VisitDate': '2015-03-01'}, {'UserID': 'U2', 'VisitDate': '2015-03-18'}]
#Create dataframe of visits
visitDF = pd.DataFrame(data=visits)
#Convert VisitDate from object to date
visitDF['VisitDate'] = pd.to_datetime(visitDF['VisitDate'])
#Add new column to build the month-only
visitDF['VisitMonth'] = visitDF['VisitDate'].dt.to_period('M')
#Group by to get the visits by user by month
visits_grouped = visitDF.groupby(['UserID', 'VisitMonth']).agg(['count'])
#Remove the index on UserID so can `merge`
visits_grouped.reset_index(inplace=True)
#Grouped by dataframe
cohortDF = visits_grouped.merge(usersDF[['UserID', 'SignUpMonth']], on='UserID', how='left')
此groupby / merge仅构建一个有访问的数据框,我希望能够聚合其他字段,无论是否有访问。
UserID VisitMonth VisitDate
count
0 U1 2014-01 1
1 U1 2014-02 1
2 U1 2014-03 2
3 U1 2014-04 1
4 U1 2014-10 1
5 U1 2015-01 1
6 U2 2015-01 2
7 U2 2015-03 2
我认为for loop
可以用于此,但我无法分解DF的DF /数据类型。这是一些粗略的(根本没有工作)代码,我在想这个:
注意:此代码不起作用
for user in range(0, len(usersDF)):
TheUserID = usersDF['UserID'][user]
TheSignUpMonth = usersDF['SignUpMonth'][user]
AnalysisMonth = pd.to_datetime(datetime.datetime(2015,03,31)).to_period('M')
numperiods = AnalysisMonth - TheSignUpMonth
months = pd.date_range(TheSignUpMonth, periods=numperiods, freq='M')
for month in months:
df.append([TheUserID, TheSignUpMonth, month])
这种方法存在一些问题。
datetime
方法可以确定两个日期之间的天数/月数等,但是尝试计算月份系列之间的差异是行不通的。 我如何构建我想要的数据帧?
答案 0 :(得分:0)
以下是一种使用示例dataframe
:
添加一个辅助列进行聚合(需要在数据透视表的索引中使用所有其他列时)
visitDF['counter'] = 1
然后创建一个数据透视表,以便VisitDate
列本身位于索引中,其他维度位于另一个维度中。
df =pd.pivot_table(visitDF,index = 'VisitDate', columns=['VisitMonth','UserID'],\
values='counter', aggfunc='sum').
然后将索引重新采样为day。这会为没有值
的天创建NAN
值
df =df.resample('D',how='sum')
然后取消堆叠框架,重置索引并用{0}填充NAN
以获得所需的框架。
df.unstack().reset_index().fillna(0)