Python Pandas计算日期之间的平均天数

时间:2017-07-21 15:17:17

标签: python pandas if-statement group-by average

使用以下python pandas dataframe df:

Customer_ID | Transaction_ID
ABC            2016-05-06-1234
ABC            2017-06-08-3456
ABC            2017-07-12-5678
ABC            2017-12-20-6789
BCD            2016-08-23-7891
BCD            2016-09-21-2345
BCD            2017-10-23-4567

遗憾的是,日期隐藏在transaction_id字符串中。我用这种方式编辑了数据框。

#year of transaction
df['year'] = df['Transaction_ID'].astype(str).str[:4]

#date of transaction
df['date'] = df['Transaction_ID'].astype(str).str[:10]

#format date
df['date']=pd.to_datetime(df['date'], format='%Y-%m-%d')

#calculate visit number per year
df['visit_nr_yr'] = df.groupby(['Customer_ID', 'year']).cumcount()+1

现在df看起来像这样:

Customer_ID | Transaction_ID    | year  | date        |visit_nr_yr 
ABC            2016-05-06-1234    2016    2016-05-06    1            
ABC            2017-06-08-3456    2017    2017-06-08    1            
ABC            2017-07-12-5678    2017    2017-07-12    2            
ABC            2017-12-20-6789    2017    2017-12-20    3            
BCD            2016-08-23-7891    2016    2016-08-23    1            
BCD            2016-09-21-2345    2016    2016-09-21    2            
BCD            2017-10-23-4567    2017    2017-10-23    1            

我需要计算以下内容:

  • 访问次数之间的平均天数(因此在1& 2和2& 3之间)
  • 一般来说,访问之间的平均天数

首先,我想包括以下列" days_between_visits_by year" (数学由Customer_ID完成):

Customer_ID|Transaction_ID  |year| date       |visit_nr_yr|days_bw_visits_yr 
ABC         2016-05-06-1234  2016  2016-05-06   1             NaN
ABC         2017-06-08-3456  2017  2017-06-08   1             NaN
ABC         2017-07-12-5678  2017  2017-07-12   2             34
ABC         2017-12-20-6789  2017  2017-12-20   3             161
BCD         2016-08-23-7891  2016  2016-08-23   1             NaN
BCD         2016-09-21-2345  2016  2016-09-21   2             29
BCD         2017-10-23-4567  2017  2017-10-23   1             NaN

请注意,我故意避免使用0并保留Nans,以防有人在同一天进行两次访问。

接下来,我想计算一次访问之间的平均天数(因此在1和2之间以及在一年内2到3之间)。寻找这个输出:

avg_days_bw_visits_1_2 | avg_days_bw_visits_2_3
31.5                     161

最后,我想计算一般访问之间的平均天数:

output: 203.8 
#the days between visits are 398,34,161,29,397 and the average of those 
 numbers is 203.8

我一直坚持如何创建专栏" days_bw_visits_yr"。 Nans必须被排除在数学之外。

3 个答案:

答案 0 :(得分:3)

您可以通过更改" date"来获取之前的访问日期(按客户和年份分组)。列向下1:

df['previous_visit'] = df.groupby(['Customer_ID', 'year'])['date'].shift()

由此可见,两次访问之间的差异只是差异:

df['days_bw_visits'] = df['date'] - df['previous_visit']

要计算均值,请将日期增量对象转换为天数:

df['days_bw_visits'] = df['days_bw_visits'].apply(lambda x: x.days)

平均访问天数:

df.groupby('visit_nr_yr')['days_bw_visits'].agg('mean')

df['days_bw_visits'].mean()

答案 1 :(得分:1)

来源DF:

In [96]: df
Out[96]:
  Customer_ID   Transaction_ID
0         ABC  2016-05-06-1234
1         ABC  2017-06-08-3456
2         ABC  2017-07-12-5678
3         ABC  2017-12-20-6789
4         BCD  2016-08-23-7891
5         BCD  2016-09-21-2345
6         BCD  2017-10-23-4567

解决方案:

df['Date'] = pd.to_datetime(df.Transaction_ID.str[:10])
df['visit_nr_yr'] = df.groupby(['Customer_ID', df['Date'].dt.year]).cumcount()+1
df['days_bw_visits_yr'] = \
    df.groupby(['Customer_ID', df['Date'].dt.year])['Date'].diff().dt.days

结果:

In [98]: df
Out[98]:
  Customer_ID   Transaction_ID       Date  visit_nr_yr  days_bw_visits_yr
0         ABC  2016-05-06-1234 2016-05-06            1                NaN
1         ABC  2017-06-08-3456 2017-06-08            1                NaN
2         ABC  2017-07-12-5678 2017-07-12            2               34.0
3         ABC  2017-12-20-6789 2017-12-20            3              161.0
4         BCD  2016-08-23-7891 2016-08-23            1                NaN
5         BCD  2016-09-21-2345 2016-09-21            2               29.0
6         BCD  2017-10-23-4567 2017-10-23            1                NaN

答案 2 :(得分:0)

值得一提的是,除了获得上次购买之间的时间差

df['previous_visit'] = df.groupby(['Customer_ID', 'year'])['date'].shift()
df['days_bw_visits'] = df['date'] - df['previous_visit'] 
df['days_bw_visits'] = df['days_bw_visits'].apply(lambda x: x.days)

在执行.shift()之前,应确保按组值对日期进行排序,以避免days_bw_visits为负数

df = df.sort_values(['Customer_ID', 'DATE_D'])