【问题标题】:update a Dataframe from a different Dataframe based on a matching value根据匹配值从不同的 Dataframe 更新 Dataframe
【发布时间】:2021-08-12 10:28:13
【问题描述】:

我有两个数据框 DF1(33, 92) 和 DF2(11, 18) ,我想根据两个 DF 中列名“ID”的匹配值将 DF2 18 列复制到 DF1,这 18 个列在两个数据框中具有相同的名称。

我使用了以下合并:finaldf = pd.merge(DF1, DF2, on = 'ID', how ='left')

这很好用,只是它更改了 DF1 中的 18 列名称并添加了另外 18 列。所以最终的数据框形状是 (33, 109),而它应该是 DF1 形状 (33, 92) 但更新了行。

【问题讨论】:

  • 如果“ID”是 DF1 中的“索引”列,那么我们无法达到这个要求,因为我们不能有 2 行具有相同的索引 ID。
  • 查看 documentation 进行 pandas 合并。如果两个 dfs 中有相同的列名,merge 方法将添加后缀,以区分它们。您可以稍后重命名/删除多余的。
  • 这能回答你的问题吗? pandas left join and update existing column

标签: python pandas


【解决方案1】:

如果您只需要 DF2 中这 18 列的值(例如 col1、col2...col18),您可以这样做

cols_18 = ["col1",col2"....]
cols_to_use = list(set(DF1.columns) - set(cols_18))
pd.merge(DF1[cols_to_use],DF2...), on = 'ID', how ='left')

如果您想保留两个数据帧中的列,默认后缀为 _x 和 _y。但你可以像下面这样覆盖它们

pd.merge(DF1,DF2...), on = 'ID', how ='left, suffixes = ["","_new"])

现在将有 109 列,但主数据框的列名保持不变。来自 DF2 的列的后缀为“_new”

【讨论】:

  • 但此方法只会从 DF2 获取这 18 列的值,因此“ID”列不匹配的行,这些行将在这 18 列中包含 NaN。
  • 如果我们从 DF1 中删除 18 列并得到 [cols_to_use] ,这意味着我们摆脱了与 DF2 不匹配的行信息。所以从技术上讲,在基于共同值合并后,我需要 DF1 中的这些行。
  • 我无法完全理解这个问题。你能提供一个说数据帧大小为 2x2 的例子并展示你想要的吗?
【解决方案2】:

合并后的 finaldf 具有形状 (33, 109),因为它的列名称相似,但附加了 _x_y_x 来自 DF1_y 来自 DF2

您需要在合并后运行以下代码以删除这 18 个额外的“_x”和“_y”列,并将值从 DF2 复制到 DF1 其中他们在“ID”上匹配:

remove_cols = []

for col in DF2.columns:
    if col == 'ID':
        continue
    finaldf[col] = finaldf[col+'_y'].fillna(finaldf[col+'_x'])
    remove_cols += [col+'_x', col+'_y']

finaldf.drop(remove_cols, axis=1, inplace=True)

有关“_x”和“_y”列为何出现在合并数据框中的更多信息,我建议您查看pd.DataFrame.merge 的官方documentation 方法一次。 “_x”和“_y”是merge操作默认添加的后缀,用于区分名称相似的列。


或者:

pd.DataFrame.update 是 pandas 中实现您想要做的事情的一种方法。

查看here。但是使用它有一个注意事项,那就是如果您想将 DF2 中的 NaN 值复制到 DF1,那么它不会这样做。它只会更新non-NA 值:

使用来自另一个 DataFrame 的非 NA 值进行就地修改。

【讨论】:

  • 感谢您的详细回复,我会试一试,但是如果我更改 DF2 中的 18 列名称并将它们映射到 DF1 中相应的 18 列以避免名称重复,是否有帮助?如果是这样的话。下面的行是否有效。 finaldf = pd.merge(DF1[cols_18], DF2, on = 'ID', how ='left')
  • DF1 和 DF2 中的 18 个列名已经相同了吧?这就是“_x”和“_y”被合并添加的原因。
  • 谢谢,对,如果我更改 DF2 列名,我如何将它们映射回 DF1,而它们有不同的列名?它是这样工作的吗?
  • 嗨,对不起,我不活跃。我不明白您的问题“在合并后跳过 _x 的 18 列中的填充数据”。如果您有一些新的要求、想要涵盖的场景,您可以随时发布新问题。这样,您将能够更好地解释您的用例。如果您发布它,请告诉我,会帮助您:)
  • 合并后您的 df 中没有 finaldf[col]。这个循环实际上是在创建它。合并后你有finaldf[col+'_x']finaldf[col+'_y']。现在pd.merge 已经负责将值从 DF2 复制到 DF1 以匹配 ID。这些存储在finaldf[col+'_y'] 中。在它们不匹配的地方,您希望保持 DF1 的值正确。这就是这条 python 行在循环中所做的。在这个过程中,由于您不希望finaldf 中的'_x' 和'_y' 列,我基本上创建了finaldf['col'] 来存储最终数据。它不在您合并的finaldf 中,您可以设置条件。
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多