[英]Merging and updating multiple pandas dataframes with overlapping columns
我現在很難合並和更新 Pandas 數據幀。
我有一堆 CSV 文件,我正在用 pandas 解析(這不是問題)。 在極少數情況下,我有多個文件,其中包含兩個文件中都存在的一些列。
因此,例如,假設我有:
import pandas as pd
a = pd.DataFrame({"A": [0, 1, 2, 3], "B": [4, 5, 6, 7]}, index=[0,1,2,3])
b = pd.DataFrame({"A": [11, 12, 13, 14]}, index=[41,51,61,71])
c = pd.DataFrame({"A": [110, 111, 113]}, index=[0,1,3])
我想要的是這個 dataframe:
A B
0 110 4
1 111 5
2 2 6
3 113 7
41 11 NaN
51 12 NaN
61 13 NaN
71 14 NaN
Pandas 有這個很好的指南: Merge, join, concatenate and compare 。 但是我找不到解決我想要實現的目標的方法。
例如a.join(b, how="outer")
引發ValueError: columns overlap but no suffix specified: Index(['A'], dtype='object')
。 傳遞rsuffix="R"
不是一個選項,因為最終結果是:
A B AR
0 0.0 4.0 NaN
1 1.0 5.0 NaN
2 2.0 6.0 NaN
3 3.0 7.0 NaN
41 NaN NaN 11.0
51 NaN NaN 12.0
61 NaN NaN 13.0
71 NaN NaN 14.0
不完全是我想要的。
pd.merge(a, b, how="outer")
看起來很有前途,但也不太正確,因為索引被忽略了:
A B
0 0 4.0
1 1 5.0
2 2 6.0
3 3 7.0
4 11 NaN
5 12 NaN
6 13 NaN
7 14 NaN
傳遞left_index=True
和right_index=True
會產生類似於.join(..., rsuffix="_x", lsuffix="_y")
,所以不是我想要的。
使用update
幾乎是我想要的, a.merge(c)
將a
修改為
A B
0 110.0 4
1 111.0 5
2 2.0 6
3 113.0 7
但是a.update(b)
什么都不做(我假設是因為a
和b
的索引是分離的)。
那么,我想要的甚至可以用一行代碼實現嗎?
編輯
我想出了這個:
> lll = pd.concat([a,b, c]).sort_index()
> pd.concat([a,b,c]).sort_index().drop_duplicates().groupby(a.index).last()
A B
0 110 4.0
1 111 5.0
2 2 6.0
3 113 7.0
41 11 NaN
51 12 NaN
61 13 NaN
71 14 NaN
這就是我想要的,問題是:這是正確的還是巧合,它產生的結果與我想要的相同?
您如何確定哪個“A”列具有優先權?
按照我閱讀文件的順序。 這些文件由設備(對我來說是一種“黑匣子”)生成,並生成其中包含日期的文件。 所以我這樣做:
tasks = [parse_csv_file(fn) for fn in sorted(glob.glob("*.csv"))]
results = await asyncio.gather(*tasks)
我想這樣做(沒有錯誤檢查,因為這是一個例子):
results = iter(results)
merged_df = next(results)
for df in results:
merged_df = the_magic_function_Im_looking_for(df)
嘗試在 axis=1 上使用concat
+ groupby last
合並數據幀,然后獲取每個列組的“最后”有效值:
df = pd.concat([a, b, c], axis=1).groupby(level=0, axis=1).last()
df
:
A B
0 110.0 4.0
1 111.0 5.0
2 2.0 6.0
3 113.0 7.0
41 11.0 NaN
51 12.0 NaN
61 13.0 NaN
71 14.0 NaN
或concat
ing long 並獲得每行索引的最后有效行,這要歸功於@anky :
df = pd.concat([a, b, c]).groupby(level=0).last()
df
:
A B
0 110 4.0
1 111 5.0
2 2 6.0
3 113 7.0
41 11 NaN
51 12 NaN
61 13 NaN
71 14 NaN
使用combine_first
reduce
ing:
from functools import reduce
to_merge = [c, b, a]
result = reduce(pd.DataFrame.combine_first, to_merge)
它連續將combine_first
應用於列表的條目以結束所有組合,即最后減少 dataframe。
(如果to_merge
帶有相反的順序,我們可以將reversed(to_merge)
放在reduce
中),
要得到
>>> result
A B
0 110.0 4.0
1 111.0 5.0
2 2.0 6.0
3 113.0 7.0
41 11.0 NaN
51 12.0 NaN
61 13.0 NaN
71 14.0 NaN
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.