我有一个包含股票报价机名称和日期作为两列的数据框,我想用与这两列匹配的另一个更大的数据框的价格值更新这个数据框
如:df1:
ticker Date
AAPL 2022-01-03
GE 2022-04-18
df2:
ticker Date Close
AAPL 2022-01-02 120
AAPL 2022-01-03 122
AAPL 2022-01-04 125
AAPL 2022-01-05 121
.
.
.
GE 2022-04-16 20
GE 2022-04-17 22
GE 2022-04-18 25
GE 2022-04-19 21
输出应该是:
ticker Date Close
AAPL 2022-01-03 122
GE 2022-04-18 25
我可以做一个循环和更新行,行,但我想检查是否有一个神谕的方式使用一系列/向量…
TL;DR:如果你可以提前索引你的数据帧,你可以做得更好10000倍大于merge()
对于两个数据帧(一个有500行,一个有2500万行)的每个单独连接;如果您只对这样的数据框进行单个连接,merge()与其他方法一样快。
你的问题是:
我有一个包含股票股票名称和日期作为两列的数据框,我想用与这两列匹配的另一个更大的数据框的价格值更新这个数据框
…你问:
我想检查是否有使用整个系列/向量的python方法
如果您的问题是在这个单一数据帧查询的上下文中提出的,那么您可能无法获得比merge()
更好的性能。
但是,如果您可以选择初始化您的数据帧以使用ticker, Date
作为它们的索引,或者如果您至少可以在需要运行您问题中描述的多种查询之前将它们的索引设置为ticker, Date
,那么您可以击败merge()
。
下面是针对500行df1和2500万行df2的6种不同策略的基准测试:
Timeit results:
foo_1 (merge) ran in 23.043055499998445 seconds
foo_2 (indexed join) ran in 51.69773360000181 seconds
foo_3 (pre-indexed join) ran in 0.0027679000013449695 seconds
foo_4 (pre-indexed df1 join) ran in 24.431038499998976 seconds
foo_5 (merge right) ran in 22.99117219999971 seconds
foo_6 (pre-indexed assign) ran in 0.007970200000272598 seconds
请注意,pre-indexed join
比merge
快10,000倍(pre-indexed assign
也快3,000倍),主要是因为预索引的数据帧通过索引访问哈希表,索引的键搜索时间为O(1),而非索引键的最坏情况为O(n)。然而,indexed join
的速度是merge
的两倍多,因为indexed join
包含了初始索引工作(对于多个查询,例如您的问题中的查询,可以只做一次,并且从pre-indexed join
中排除)。
各种策略的解释:
merge
策略不使用索引indexed join
策略包括索引两个数据帧的时间。pre-indexed join
策略不包括索引两个数据帧的初始开销。pre-indexed df1 join
策略不包括索引df1的初始开销,但可以使用未索引的df2。merge right
策略交换df1和df2作为merge()
的对象和参数。pre-indexed assign
策略不使用merge()
或join()
,而是从df2到df1的新列进行索引对齐赋值。
每个策略的代码如下:
df1_orig = pd.DataFrame([('A'+str(i) , f'{2020+i//365}-{(i//28)%12 + 1}-{i%28 + 1}') for i in range(500)], columns=['ticker', 'Date'])
print(df1_orig)
df2_orig = pd.DataFrame([('A'+str(i) , f'{2020+(i%500)//365}-{((i%500)//28)%12 + 1}-{(i%500)%28 + 1}', (10 * i + 1) % 300) for i in range(25_000_000)], columns=['ticker', 'Date', 'Close'])
print(df2_orig)
df1_indexed_orig = df1_orig.set_index(['ticker', 'Date'])
df2_indexed_orig = df2_orig.set_index(['ticker', 'Date'])
# merge
def foo_1(df1, df2):
df1 = df1.merge(df2, on = ['ticker', 'Date'], how = 'left')
return df1
# indexed join
def foo_2(df1, df2):
df1.set_index(['ticker', 'Date'], inplace=True)
df2.set_index(['ticker', 'Date'], inplace=True)
df1 = df1.join(df2)
return df1
# pre-indexed join
def foo_3(df1, df2):
# called with df1_indexed_orig and df2_indexed_orig
df1 = df1.join(df2)
return df1
# pre-indexed df1 join
def foo_4(df1, df2):
# called with df1_indexed_orig
df1 = df2.join(df1, on = ['ticker', 'Date'], how = 'right')
return df1
# merge right
def foo_5(df1, df2):
df1 = df2.merge(df1, on = ['ticker', 'Date'], how = 'right')
return df1
# pre-indexed assign
def foo_6(df1, df2):
# called with df1_indexed_orig and df2_indexed_orig
df1 = df1.assign(Close=df2.Close)
return df1
试穿合并这两个列:
df1.merge(df2, on = ['ticker', 'Date'], how = 'left')