使用日期索引对 DataFrame 进行矢量化

vectorization on DataFrame with date index

我有一个像这样的 DataFrame,有几十万行:

                            A        B
Date                
2020-01-02 09:59:45     -0.007641    1
2020-01-02 10:20:11      0.000211    1
2020-01-02 10:30:27     -0.001294    0
2020-01-02 11:42:54     -0.003468    0
2020-01-02 12:03:22     -0.005559    1

我的想法是,我想要一列 C,其中包含 A + 1 系列的 .cumprod() 的最后一个元素,每次 B == 1 并从日期开始该行。

因此,例如,在第二行,B == 1,我从对应的日期 2020-01-02 10:20:11 中提取 A 列,其中 df.loc['2020-01-02 10:20:11':, 'A'] :

                            A        
Date                
2020-01-02 10:20:11      0.000211    
2020-01-02 10:30:27     -0.001294    
2020-01-02 11:42:54     -0.003468    
2020-01-02 12:03:22     -0.005559    

那我加1,

                          A
Date
2020-01-02 10:20:11    1.000211
2020-01-02 10:30:27    0.998706
2020-01-02 11:42:54    0.996532
2020-01-02 12:03:22    0.994441

我做了(df.loc['2020-01-02 10:20:11':, 'A']+1).cumprod(),我们得到:

                          A
Date
2020-01-02 10:20:11    1.000211
2020-01-02 10:30:27    0.998916
2020-01-02 11:42:54    0.995452
2020-01-02 12:03:22    0.989919

最后一个值是 0.989919 然后在我的初始 DataFrame 中它看起来像这样:

                            A        B    C
Date                
2020-01-02 09:59:45     -0.007641    1   a_value
2020-01-02 10:20:11      0.000211    1   0.989919
2020-01-02 10:30:27     -0.001294    0   0
2020-01-02 11:42:54     -0.003468    0   0
2020-01-02 12:03:22     -0.005559    1   another_value

所以我最近发现了矢量化,并尝试在那里应用它。我首先尝试了这个,看看我是否可以获得列 C 中每一行的日期:

def last_cumul(date):
    return date

df['C'] = last_cumul(df.index)

有效

                            A        B            C
Date                
2020-01-02 09:59:45     -0.007641    1   2020-01-02 09:59:45
2020-01-02 10:20:11      0.000211    1   2020-01-02 10:20:11
2020-01-02 10:30:27     -0.001294    0   2020-01-02 10:30:27
2020-01-02 11:42:54     -0.003468    0   2020-01-02 11:42:54
2020-01-02 12:03:22     -0.005559    1   2020-01-02 12:03:22

所以我决定这样做:

def last_cumul(date):
    return (df.loc[date:, 'A']+1).cumprod()[-1]

df['C'] = last_cumul(df.index)

但是这次我遇到了错误:

TypeError: Cannot convert input [DatetimeIndex(['2020-01-02 09:59:45', '2020-01-02 10:20:11',
               '2020-01-02 10:30:27', '2020-01-02 11:42:54',
               '2020-01-02 12:03:22'],
              dtype='datetime64[ns]', name='Date', freq=None)] of type <class 'pandas.core.indexes.datetimes.DatetimeIndex'> to Timestamp

可以使用矢量化来实现,否则我将不得不遍历 DataFrame 吗?

谢谢!

对于每个B=1,选择具有较大日期的行并乘以A+1。当我们使用 cumprod 时,行的顺序并不重要,因为我们只选择 cumprod 的最后一个元素。 考虑到这一点,我们可以看到较大日期所需的行包含在较小的日期中。因此,为了节省计算量,我们应该找到较大日期的 cumprod,然后将其重新用于较小的日期。这是通过对 Date 进行反向排序并在 A+1 上应用 cumprod 自然完成的,没有任何花哨的算法。

df.sort_values(by='Date',ascending=False, inplace=True)
df['C']=(df['A']+1).cumprod()*df['B']
df.sort_index(inplace=True)

这有两个目的,1> 将计算复杂度从 O(N2) 降低到 O(Nlog(N)) 和 2> 使数据稍微更有条理以进行矢量化