使用日期索引对 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> 使数据稍微更有条理以进行矢量化
我有一个像这样的 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> 使数据稍微更有条理以进行矢量化