首页 > 解决方案 > 合并和更新具有重叠列的多个熊猫数据框

问题描述

我现在很难合并和更新 Pandas 数据框。

我有一堆我正在用 pandas 解析的 CSV 文件(这不是问题)。在极少数情况下,我有多个文件,其中包含两个文件中存在的一些列。

因此,例如,假设我有:

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])

我想要的是这个数据框:

     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 和 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=Trueright_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)的索引是分离的)。ab

那么,我想要的甚至可以用一行代码实现吗?

编辑

我想出了这个:

> 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)

标签: pythonpandasdataframe

解决方案


尝试使用concat+ groupby laston axis=1 合并数据框,然后获取每个列组的“最后一个”有效值:

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由于@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

推荐阅读