合并数据框但不按合并键排序

1 投票
1 回答
61 浏览
提问于 2025-04-11 21:53

我想把 df1df2 合并成 df3,并且保持顺序。我的示例代码中加了 sort=False,但是结果并没有按我预期的那样工作。

import pandas as pd

data1 = [
    ['4A', 1],
    ['3B', 2],
    ['2C', 3],
    ['1D', 4],
    ]
data2 = [
    ['2C', 9],
    ['4A', 3],
    ['6F', 2],
    ['5G', 1],
    ]

df1 = pd.DataFrame(data1, columns=['name', 'value'])
df2 = pd.DataFrame(data2, columns=['name', 'value'])

df3 = pd.merge(df1, df2, how='outer', on='name', sort=False)
df3 = df3.rename({'value_x': 'v1', 'value_y': 'y2'}, axis=1)
print(df1)
print(df2)
print(df3)

输出结果:

  name  value
0   4A      1
1   3B      2
2   2C      3
3   1D      4
  name  value
0   2C      9
1   4A      3
2   6F      2
3   5G      1
  name   v1   y2
0   1D  4.0  NaN
1   2C  3.0  9.0
2   3B  2.0  NaN
3   4A  1.0  3.0
4   5G  NaN  1.0
5   6F  NaN  2.0

期望的输出结果:

  name   v1   y2
0   4A  1.0  3.0
1   3B  2.0  NaN
2   2C  3.0  9.0
3   1D  4.0  NaN
4   6F  NaN  2.0
5   5G  NaN  1.0

1 个回答

2

假设你有一些已经排好序的数据索引,首先用reset_index来重置索引,然后再用merge来合并数据,最后用sort_values来排序:

df3 = (pd.merge(df1.reset_index(), df2.reset_index(),
                how='outer', on='name', sort=False)
         .sort_values(by=['index_x', 'index_y'],
                      ignore_index=True)
         .drop(columns=['index_x', 'index_y'])
         .rename({'value_x': 'v1','value_y':'y2'}, axis=1)
      )

对于更通用的情况:

df3 = (pd.merge(df1.assign(index=np.arange(len(df1))),
                df2.assign(index=np.arange(len(df2))),
                how='outer', on='name', sort=False)
         .sort_values(by=['index_x', 'index_y'],
                      ignore_index=True)
         .drop(columns=['index_x', 'index_y'])
         .rename({'value_x': 'v1','value_y':'y2'}, axis=1)
      )

另外,你也可以使用 df1['name']df2['name'] 的并集来reindex

idx = pd.concat([df1['name'], df2['name']]).drop_duplicates()

df3 = (pd.merge(df1, df2, how='outer', on='name', sort=False)
         .set_index('name').reindex(idx).reset_index()
         .rename({'value_x': 'v1','value_y':'y2'}, axis=1)
      )

输出结果:

  name   v1   y2
0   4A  1.0  3.0
1   3B  2.0  NaN
2   2C  3.0  9.0
3   1D  4.0  NaN
4   6F  NaN  2.0
5   5G  NaN  1.0

撰写回答