簡體   English   中英

pandas 在列值匹配時使用來自另一個數據幀的值更新數據幀

[英]pandas update a dataframe with values from another dataframe on the match of column values

我有一個數據框,其中股票代碼名稱和日期為兩列,我想用另一個與這兩列匹配的更大數據框的價格值來更新這個數據框

例如: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

我可以做一個循環並逐行更新,但我想檢查是否有使用整個系列/向量的pythonic方式......

TL;DR :如果您可以提前索引您的數據幀,那么對於兩個數據幀的每個單獨連接(一個有 500 行,一個有 2500 萬行),您可以比merge()好大約 10,000 倍 如果您只對此類數據幀進行一次連接,則 merge() 與其他方法一樣快。


你的問題說:

我有一個數據框,其中股票代碼名稱和日期為兩列,我想用另一個與這兩列匹配的更大數據框的價格值來更新這個數據框

...你問:

我想檢查是否有使用整個系列/向量的pythonic方式

如果您的問題是在這個單一數據框查詢的上下文中提出的,那么您可能無法獲得比merge()更好的性能。

但是,如果您可以選擇初始化數據框以使用ticker, Date作為它們的索引,或者如果您至少可以將它們的索引設置為ticker, Date ,然后需要運行問題中描述的多個查詢,那么您可以擊敗merge()

以下是 df1 500 行和 df2 2500 萬行的 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 joinmerge快約 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')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM