【问题标题】:Python Pandas Calculate average days between datesPython Pandas 计算日期之间的平均天数
【发布时间】:2017-12-27 17:10:35
【问题描述】:

使用以下 python pandas 数据框 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必须被排除在数学之外。

【问题讨论】:

  • 你能发布你想要的(最终)数据集吗?
  • @MaxU,列 days_bw_visits_yr 的数据框是所需的最终数据集 - 然后在该数据集上完成另外两个计算,但不会添加到数据框中,因为它们是聚合平均值;谢谢

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


【解决方案1】:

您可以通过将“日期”列下移 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()

【讨论】:

  • 非常感谢 - 现在测试这个解决方案;班次选项听起来不错
  • 我不幸收到“数据错误:错误消息没有要聚合的数字类型”我认为这与日期不是日期类型有关?
  • 对于任何将其视为解决方案的人。确保在执行shift() 之前对日期列进行排序。所以第一行代码应该是df = df.sort_values(by='date) 然后继续parasu的代码。我只花了 30 分钟试图找出代码出了什么问题。我的 df 已经排序了 99%,除了几行导致一些奇怪的负值。
【解决方案2】:

来源 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

【讨论】:

  • 谢谢@MaxU;我完全按照您的步骤操作,但对于 days_bw_visits_yr 的最后一行,我收到此错误 AttributeError: Can only use .dt accessor with datetimelike values
【解决方案3】:

值得注意的是,除了获得上次购买之间的时间差异

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 2022-01-05
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 2019-07-12
    • 1970-01-01
    相关资源
    最近更新 更多