【问题标题】:python pandas: vectorized time series window functionpython pandas:矢量化时间序列窗口函数
【发布时间】:2018-05-13 19:16:02
【问题描述】:

我有一个以下格式的熊猫数据框:

'customer_id','transaction_dt','product','price','units'
1,2004-01-02,thing1,25,47
1,2004-01-17,thing2,150,8
2,2004-01-29,thing2,150,25
3,2017-07-15,thing3,55,17
3,2016-05-12,thing3,55,47
4,2012-02-23,thing2,150,22
4,2009-10-10,thing1,25,12
4,2014-04-04,thing2,150,2
5,2008-07-09,thing2,150,43

我编写了以下代码来创建两个指示 30 天窗口的新字段:

import numpy as np
import pandas as pd

start_date_period = pd.period_range('2004-01-01', '12-31-2017', freq='30D')
end_date_period = pd.period_range('2004-01-30', '12-31-2017', freq='30D')

def find_window_start_date(x):
    window_start_date_idx = np.argmax(x < start_date_period.end_time)
    return start_date_period[window_start_date_idx]

df['window_start_dt'] = df['transaction_dt'].apply(find_window_start_date)

def find_window_end_date(x):
    window_end_date_idx = np.argmin(x > end_date_period.start_time)
    return end_date_period[window_end_date_idx]

df['window_end_dt'] = df['transaction_dt'].apply(find_window_end_date)

不幸的是,为我的应用程序按行申请太慢了。如果可能的话,我将不胜感激有关矢量化这些函数的任何提示。

编辑:

生成的数据框应具有以下布局:

'customer_id','transaction_dt','product','price','units','window_start_dt','window_end_dt'

在正式意义上,它不需要重新采样或窗口化。它只需要添加“window_start_dt”和“window_end_dt”列。当前代码有效,如果可能,只需对其进行矢量化即可。

【问题讨论】:

  • 只是为了确认一下,您只想提取属于该 30 天窗口的最后一个日期(出现在您的数据中),对吧?
  • @AntoineZambelli 我想我明白你的意思了。我实际上不需要另外做一个 groupby 操作,所以不需要在 windows 中选择第一个/最后一个日期。仅适用于现有行。如有误解,请见谅。
  • 好吧,希望我理解正确,我想你想要resample

标签: python pandas numpy vectorization


【解决方案1】:

编辑 2pandas.cut 是内置的:

    tt=[[1,'2004-01-02',0.1,25,47],
[1,'2004-01-17',0.2,150,8],
[2,'2004-01-29',0.2,150,25],
[3,'2017-07-15',0.3,55,17],
[3,'2016-05-12',0.3,55,47],
[4,'2012-02-23',0.2,150,22],
[4,'2009-10-10',0.1,25,12],
[4,'2014-04-04',0.2,150,2],
[5,'2008-07-09',0.2,150,43]]



start_date_period = pd.date_range('2004-01-01', '12-01-2017', freq='MS')
end_date_period = pd.date_range('2004-01-30', '12-31-2017', freq='M')

df = pd.DataFrame(tt,columns=['customer_id','transaction_dt','product','price','units'])
df['transaction_dt'] = pd.Series([pd.to_datetime(sub_t[1],format='%Y-%m-%d') for sub_t in tt])

the_cut = pd.cut(df['transaction_dt'],bins=start_date_period,right=True,labels=False,include_lowest=True)

df['win_start_test'] = pd.Series([start_date_period[int(x)] if not np.isnan(x) else 0 for x in the_cut])
df['win_end_test'] = pd.Series([end_date_period[int(x)] if not np.isnan(x) else 0 for x in the_cut])

print(df.head())

win_start_testwin_end_test 应该等于使用您的函数计算的对应值。

ValueError 来自未在相关行中将 x 转换为 int。我还添加了一个NaN 检查,尽管这个玩具示例不需要它。

请注意对pd.date_range 的更改以及对月初和月底标志MMS 的使用,以及将日期字符串转换为datetime

【讨论】:

  • 谢谢,但我不认为这是我想要的。我希望能够使用我定义的任意窗口,而不是链接到日历日期。也不能保证这些窗口彼此相邻。
  • 如果任意窗口没有链接到日历日期,那么我真的很困惑——也许你可以发布预期的输出?我认为resample 适用于非连续数据(只需要排序)。也许你想要rolling
  • 添加了一些解释。在开始进行 groupby 类型计算之前,我必须将结果数据与一堆其他数据源连接/合并,所以我只需要应用窗口日期,没有其他任何改变。如果我重新采样/滚动,我会过早地进行转换/聚合。
  • 嗯,我收到了一个值错误。我认为这与日期是否超出定义的范围有关,这也是可能的。
  • 错误在哪一行被抛出?详情?
猜你喜欢
  • 2021-08-04
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 2017-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多