【问题标题】:Using Pandas .diff() on a time series column with a groupby在带有 groupby 的时间序列列上使用 Pandas .diff()
【发布时间】:2016-05-05 02:17:37
【问题描述】:

我有一个CSV 客户购买的文件,我读到了Pandas Dataframe,没有特定的顺序。我想为每次购买添加一列,并显示自上次购买以来经过了多长时间,按客户分组。我不确定差异在哪里,但它们太大了(即使在几秒钟内)。

CSV:

Customer Id,Purchase Date
4543,1/1/2015
4543,2/5/2015
4543,3/15/2015
2322,1/1/2015
2322,3/1/2015
2322,2/1/2015

Python:

import pandas as pd
import time
start = time.time()
data = pd.read_csv('data.csv', low_memory=False)
data = data.sort_values(by=['Customer Id', 'Purchase Date'])
data['Purchase Date'] = pd.to_datetime(data['Purchase Date'])
data['Purchase Difference'] = (data.groupby(['Customer Id'])['Purchase Date']
                         .diff()
                         .fillna('-')
                       )
print data

输出:

    Customer Id Purchase Date Purchase Difference
3         2322    2015-01-01                   -
5         2322    2015-02-01    2678400000000000
4         2322    2015-03-01    2419200000000000
0         4543    2015-01-01                   -
1         4543    2015-02-05    3024000000000000
2         4543    2015-03-15    328320000000000

期望的输出:

   Customer Id Purchase Date  Purchase Difference
3         2322    2015-01-01                  -
5         2322    2015-02-01              31 days
4         2322    2015-03-01              28 days
0         4543    2015-01-01                  -
1         4543    2015-02-05              35 days
2         4543    2015-03-15              38 days

【问题讨论】:

  • 最后一个数据帧真的是您想要的输出,还是那里的差异太大?
  • @IanS 谢谢。我不是那个意思。更正了问题。

标签: python python-2.7 pandas


【解决方案1】:

您只需将diff 应用于Purchase Date 列,将其转换为时间戳即可。

df['Purchase Date'] = pd.to_datetime(df['Purchase Date'])
df.sort_values(['Customer Id', 'Purchase Date'], inplace=True)    
df['Purchase Difference'] = \
    [str(n.days) + ' day' + 's' if n > pd.Timedelta(days=1) else '' if pd.notnull(n) else "" 
     for n in df.groupby('Customer Id', sort=False)['Purchase Date'].diff()]

>>> df
   Customer Id Purchase Date Purchase Difference
3         2322    2015-01-01                    
5         2322    2015-02-01             31 days
4         2322    2015-03-01             28 days
0         4543    2015-01-01                    
1         4543    2015-02-05             35 days
2         4543    2015-03-15             38 days
6         4543    2015-03-15                    

【讨论】:

    【解决方案2】:

    我认为您可以添加read_csv 参数parse_dates 用于解析datetimesort_values 和最后一个groupbydiff

    import pandas as pd
    import io
    
    temp=u"""Customer Id,Purchase Date
    4543,1/1/2015
    4543,2/5/2015
    4543,3/15/2015
    2322,1/1/2015
    2322,3/1/2015
    2322,2/1/2015"""
    #after testing replace io.StringIO(temp) to filename
    data = pd.read_csv(io.StringIO(temp), parse_dates=['Purchase Date'])
    
    data.sort_values(by=['Customer Id', 'Purchase Date'], inplace=True)
    
    data['Purchase Difference'] = data.groupby(['Customer Id'])['Purchase Date'].diff()
    print data
       Customer Id Purchase Date  Purchase Difference
    3         2322    2015-01-01                  NaT
    5         2322    2015-02-01              31 days
    4         2322    2015-03-01              28 days
    0         4543    2015-01-01                  NaT
    1         4543    2015-02-05              35 days
    2         4543    2015-03-15              38 days
    

    【讨论】:

    • 我喜欢你的第二种方法,这基本上是我所做的,但是添加 fillna() 函数似乎是导致大量数字的原因。
    • 谢谢。什么解决方案性能更好?亚历山大的还是我的?在 read_csv 或 to_datetime 中更好地解析日期时间?谢谢。
    • 在一个 csv 文件的 60,000 行上运行每个。 @Alexander 在 7.75 秒内完成。你的在 9.39 秒内完成。
    • 如果我想计算平均值?
    • @fabio.geraci - 你认为将['Purchase Date'].diff() 更改为['Purchase Date'].transform(lambda x: x.diff().dt.days.mean()) 吗?
    猜你喜欢
    • 1970-01-01
    • 2019-12-27
    • 1970-01-01
    • 2020-07-31
    • 1970-01-01
    • 2015-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-03-09
    相关资源
    最近更新 更多