使用开始日期/结束日期在pandas中构建时间序列数据帧

时间:2015-04-24 19:58:59

标签: pandas

我正试图在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仅构建一个有访问的数据框,我希望能够聚合其他字段,无论是否有访问。

分组DF输出:

  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])

这种方法存在一些问题。

  1. 使用for循环对我来说似乎不是'panda-ish'。
  2. numperiods部分不起作用。我知道有datetime方法可以确定两个日期之间的天数/月数等,但是尝试计算月份系列之间的差异是行不通的。
  3. 由于我们正在处理字符串和熊猫时间序列对象,因此逐步构建数据帧(每个用户ID,每月)给了我一些问题。
  4. 我如何构建我想要的数据帧?

1 个答案:

答案 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)