pandas 仅将匹配的列追加到 Dataframe

mf98qq94  于 2023-04-18  发布在  其他
关注(0)|答案(4)|浏览(134)

我有一个“主” Dataframe ,我想只追加匹配列从另一个 Dataframe 排序

df:
  A  B  C
  1  2  3

df_to_append:
  A  B  C  D  E
  6  7  8  9  0

问题是,当我使用df.append()时,它还将不匹配的列追加到df。

df = df.append(df_to_append, ignore_index=True)
Out:
A  B  C   D   E
1  2  3  NaN NaN
6  7  8   9   0

但是我想要的输出是删除列D和E,因为它们不是原始 Dataframe 的一部分?也许我需要使用pd.concat?我不认为我可以使用pd.merge,因为我没有任何独特的合并。

5f0d552i

5f0d552i1#

使用concatjoin='inner

pd.concat([df,df_to_append],join='inner')
Out[162]: 
   A  B  C
0  1  2  3
0  6  7  8
w8rqjzmb

w8rqjzmb2#

只需选择两个df的公共列:
df.append(df_to_append[df.columns], ignore_index=True)

a8jjtwal

a8jjtwal3#

最简单的方法是使用df.columns获取两个 Dataframe 共有的列的列表,但是如果你不知道所有原始列都包含在df_to_append中,那么你需要找到两个集合的交集:

cols = list(set(df.columns) & set(df_to_append.columns)) 
df.append(df_to_append[cols], ignore_index=True)
t0ybt7op

t0ybt7op4#

虽然OP没有明确地这么说(也没有抱怨),但他们提到的 “类似于‘主’数据框” 对我来说意味着结果数据框的列号不应该改变。
BENYcfort的答案就是这种情况,当且仅当要追加的 Dataframe 的列名保证是原始 Dataframe 列名的严格超集。

只有Eliot K的解决方案确保了原始 Dataframe 的宽度被保留,用NaN s填充 Dataframe 中任何缺失的列。如果你遇到了这个问题,就像我一样,那么这就是要走的路。

下面我将总结这三种解决方案并展示它们的作用。

准备测试数据

让我们首先创建一些 Dataframe ,从引用 Dataframe 开始:

import pandas as pd

df = pd.DataFrame({'A': [1, 2], 'B': [4, 5], 'C': [8, 6]})

这看起来像这样:

A  B  C
0  1  4  8
1  2  5  6

现在让我们创建一组要追加的 Dataframe :

  • df_union:与df具有完全相同的列
  • df_subset_:具有df的一些列,但不是全部
  • df_intersection:有一些(但不是全部)df列,还有一些额外的列
  • df_disjoint:没有df的列
  • df_superset:包含df的所有列和一些附加列
df_union = df.copy()
df_subset = pd.DataFrame({'A': [1, 2], 'B': [4, 5]})
df_intersection = pd.DataFrame({'C': [8, 6], 'D': [1, 2], 'E': [4, 5]})
df_disjoint = pd.DataFrame({'D': [1, 2], 'E': [4, 5], 'F': [8, 6]})
df_superset = df.merge(df_disjoint, left_index=True, right_index=True)

我们最终得到每个 Dataframe 的以下列名:
| 数据框架|A|B|C|D|E|F|
| --------------|--------------|--------------|--------------|--------------|--------------|--------------|
| df|是的|是的|是的||||
| df_union|是的|是的|是的||||
| df_subset|是的|是的|||||
| df_intersection|||是的|是的|是的||
| df_disjoint||||是的|是的|是的|
| df_superset|是的|是的|是的|是的|是的|是的|
现在我们用测试数据

内部连接(BENY

pd.concat([df, df_union], join='inner')
pd.concat([df, df_subset], join='inner')
pd.concat([df, df_intersection], join='inner')
pd.concat([df, df_disjoint], join='inner')
pd.concat([df, df_superset], join='inner')

使用这种策略,我们不能得到比原始 Dataframe 中更多的列,但我们可以得到 * 更少 *(包括根本没有)。
当将每个测试 Dataframe 连接到df时,我们会得到df_out的以下列:
| 数据框架|A|B|C|
| --------------|--------------|--------------|--------------|
| df_union|是的|是的|是的|
| df_subset|是的|是的||
| df_intersection|||是的|
| df_disjoint||||
| df_superset|是的|是的|是的|

结论:

  • 防止引用 Dataframe 的扩展;删除 Dataframe 中要追加的任何其他列
    *防止引用数据框收缩
  • 如果 Dataframe 收缩是可接受的 * 或 * 如果保证要追加的 Dataframe 至少具有引用 Dataframe 中的所有列,则是好的解决方案

引用数据框cfort只追加列

df.append(df_union[df.columns], ignore_index=True)
df.append(df_subset[df.columns], ignore_index=True)
df.append(df_intersection[df.columns], ignore_index=True)
df.append(df_disjoint[df.columns], ignore_index=True)
df.append(df_superset[df.columns], ignore_index=True)

此解决方案类似于上面的内部连接,但有一个重要的区别:如果要追加的 Dataframe 不包含引用 Dataframe 中的所有列,则该操作将引发KeyError
追加以下数据框即可,df_out数据框将包含引用数据框中的所有列:
| 数据框架|A|B|C|
| --------------|--------------|--------------|--------------|
| df_union|是的|是的|是的|
| df_superset|是的|是的|是的|
对于以下 Dataframe ,引发KeyError
| 数据框架|结果|
| --------------|--------------|
| df_subset|KeyError|
| df_intersection|KeyError|
| df_disjoint|KeyError|

结论:

  • 防止引用 Dataframe 的扩展;删除 Dataframe 中要追加的任何其他列
  • 通过引发KeyError来防止引用 Dataframe 的收缩。
  • 好的解决方案,如果dataframe调整大小是不可接受的;KeyError可用于处理相对于引用 Dataframe 缺少列的 Dataframe

只在 both Dataframe Eliot K中追加列

df.append(df_union[list(set(df.columns) & set(df_union.columns))], ignore_index=True)
df.append(df_subset[list(set(df.columns) & set(df_subset.columns))], ignore_index=True)
df.append(df_intersection[list(set(df.columns) & set(df_intersection.columns))], ignore_index=True)
df.append(df_disjoint[list(set(df.columns) & set(df_disjoint.columns))], ignore_index=True)
df.append(df_superset[list(set(df.columns) & set(df_superset.columns))], ignore_index=True)

该解决方案使用与前一个相同的技术方法,但是不是从 Dataframe 中选择以附加参考 Dataframe 的所有列(其可能不可用),而是仅选择在 * 两个 * Dataframe 中可用的那些列。
通过这种方式,解决方案类似于内部连接,但由于.append()的行为,结果 Dataframe 无法收缩。相反,缺失的数据将用NaN s(甚至可能是整行)填充。
让我们看看df_out的情况:
| 数据框架|A|B|C|
| --------------|--------------|--------------|--------------|
| df_union|是的|是的|是的|
| df_subset|是的|是的|NaN|
| df_intersection|NaN|NaN|是的|
| df_disjoint|NaN|NaN|NaN|
| df_superset|是的|是的|是的|

结论:

  • 防止引用 Dataframe 的扩展;删除 Dataframe 中要追加的任何其他列
  • 通过在附加 Dataframe 的缺失列中填充NaN来防止引用 Dataframe 的收缩。
  • 如果填充缺失数据 * 是 * 并且调整数据框大小 * 是 * 不可接受的,则是一个很好的解决方案

备选:追加后选择引用列

与前一个解决方案具有相同行为的解决方案是追加 Dataframe ,然后选择引用 Dataframe 的列 afterwards

df.append(df_to_append, ignore_index=True)[df.columns]

这种解决方案更容易阅读和解析,但在大型操作上性能可能较差。

相关问题