【问题标题】:Pandas Vectorized Date Offset Operations with Vector of Differing Offsets具有不同偏移向量的 Pandas 向量化日期偏移操作
【发布时间】:2017-05-16 13:37:59
【问题描述】:

我正在尝试执行以下操作,但似乎不支持此模式下的矢量化操作。

import pandas as pd
df=pd.DataFrame([[2017,1,15,1],
             [2017,1,15,2],
             [2017,1,15,3],
             [2017,1,15,4],
             [2017,1,15,5],
             [2017,1,15,6],
             [2017,1,15,7]],
             columns=['year','month','day','month_offset'])
df['date']=df.apply(lambda g: pd.datetime(g.year,g.month,g.day),axis=1)
df['offset']=df.apply(lambda g: pd.offsets.MonthEnd(g.month_offset),axis=1)
df['date_offset']=df.date+df.offset

这是代码 sn-p 中最后一条语句返回的警告:

C:\Python3.5.2.3\WinPython-64bit-3.5.2.3\python-3.5.2.amd64\lib\site-packages\pandas\core\ops.py:533:PerformanceWarning:添加/减去数组的 DateOffsets 到 Series 未矢量化 “系列未矢量化”,PerformanceWarning)

由于性能优势,我希望将其用作矢量化操作。

谢谢。

编辑

最后,比较来自@john-zwinck 的方法:

import time
import pandas as pd
import numpy as np

df=pd.DataFrame([[2017,1,1,1],
             [2017,1,1,2],
             [2017,1,1,3],
             [2017,1,1,4],
             [2017,1,1,5],
             [2017,1,1,6],
             [2017,1,1,7]],
             columns=['year','month','day','month_offset'])

df['mydate']=df.apply(lambda g: 
pd.datetime(g.year,g.month,g.day),axis=1)
start_time=time.time()
df['pandas_offset']=df.apply(lambda g: g.mydate + 
pd.offsets.MonthEnd(g.month_offset),axis=1)
end_time=time.time()
print('Method1 {} seconds'.format(end_time-start_time))

start_time=time.time()
df['numpy_offset']=(df.mydate.values.astype('M8[M]')+ 
df.month_offset.values * np.timedelta64(1, 'M')).astype('M8[D]') - 
np.timedelta64(1, 'D')
end_time=time.time()
print('Method3 with numpy vectorization {} seconds'.format(end_time-
start_time))

结果:

index year  month  day  month_offset     mydate    offset1      final
0  2017      1    1             1 2017-01-01 2017-01-31 2017-01-31
1  2017      1    1             2 2017-01-01 2017-02-28 2017-02-28
2  2017      1    1             3 2017-01-01 2017-03-31 2017-03-31
3  2017      1    1             4 2017-01-01 2017-04-30 2017-04-30
4  2017      1    1             5 2017-01-01 2017-05-31 2017-05-31
5  2017      1    1             6 2017-01-01 2017-06-30 2017-06-30
6  2017      1    1             7 2017-01-01 2017-07-31 2017-07-31


runfile('C:/bitbucket/test/vector_dates.py', wdir='C:/bitbucket/test')
Method 1 0.003999948501586914 seconds
Method 2 with numpy vectorization 0.0009999275207519531 seconds

显然 numpy 快得多

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    真正的矢量化方法是从month_offset 构造一个numpy.timedelta64 数组,将其添加到日期数组中,然后减去numpy.timedelta64(1, 'D') 以返回上个月的最后一天。

    使用apply(lambda) 的解决方案可能要慢得多。正如警告所说,一些 Pandas 日期偏移操作没有矢量化。如果您的数据很大,最好避免使用它们。像 busday_offset()timedelta64 这样的 NumPy 工具是完全高性能的。

    【讨论】:

    • @MaxU 建议的方法更快,我曾尝试使用它,但性能也有很大的拖累,因为正如您所注意到的,它并没有真正矢量化。在我的编辑中,我使用了您的方法,这种方法更快,但不确定摆脱时间部分的最佳方法。
    【解决方案2】:

    考虑以下方法:

    In [94]: df['date'] = pd.to_datetime(df[['year','month','day']])
    
    In [95]: df['date_offset'] = df.apply(lambda x: x['date'] + pd.offsets.MonthEnd(x['month_offset']), axis=1)
    
    In [96]: df
    Out[96]:
       year  month  day  month_offset       date date_offset
    0  2017      1   15             1 2017-01-15  2017-01-31
    1  2017      1   15             2 2017-01-15  2017-02-28
    2  2017      1   15             3 2017-01-15  2017-03-31
    3  2017      1   15             4 2017-01-15  2017-04-30
    4  2017      1   15             5 2017-01-15  2017-05-31
    5  2017      1   15             6 2017-01-15  2017-06-30
    6  2017      1   15             7 2017-01-15  2017-07-31
    

    【讨论】:

    • 使用 apply 是一个循环函数,因此您不会获得矢量化的性能优势。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多