我想合并两个dataframe,并保持索引从第一帧作为合并数据集上的索引。然而,当我进行合并时,结果的DataFrame具有整数索引。我如何指定我想要保留左数据帧的索引?

In [4]: a = pd.DataFrame({'col1': {'a': 1, 'b': 2, 'c': 3}, 
                          'to_merge_on': {'a': 1, 'b': 3, 'c': 4}})

In [5]: b = pd.DataFrame({'col2': {0: 1, 1: 2, 2: 3}, 
                          'to_merge_on': {0: 1, 1: 3, 2: 5}})

In [6]: a
Out[6]:
   col1  to_merge_on
a     1            1
b     2            3
c     3            4

In [7]: b
Out[7]:
   col2  to_merge_on
0     1            1
1     2            3
2     3            5

In [8]: a.merge(b, how='left')
Out[8]:
   col1  to_merge_on  col2
0     1            1   1.0
1     2            3   2.0
2     3            4   NaN

In [9]: _.index
Out[9]: Int64Index([0, 1, 2], dtype='int64')

编辑:切换到示例代码,可以很容易地复制


当前回答

对于那些想要保持左索引和左连接之前一样的人:

def left_join(
    a: pandas.DataFrame, b: pandas.DataFrame, on: list[str], b_columns: list[str] = None
) -> pandas.DataFrame:
    if b_columns:
        b_columns = set(on + b_columns)
        b = b[b_columns]
    df = (
        a.reset_index()
        .merge(
            b,
            how="left",
            on=on,
        )
        .set_index(keys=[x or "index" for x in a.index.names])
    )
    df.index.names = a.index.names
    return df

其他回答

In [5]: a.reset_index().merge(b, how="left").set_index('index')
Out[5]:
       col1  to_merge_on  col2
index
a         1            1     1
b         2            3     2
c         3            4   NaN

请注意,对于一些左合并操作,当a和b之间有多个匹配时,您可能会得到比a中更多的行。在这种情况下,您可能需要删除重复项。

有一个非pd。使用系列合并解决方案。map和DataFrame.set_index。

a['col2'] = a['to_merge_on'].map(b.set_index('to_merge_on')['col2']))

   col1  to_merge_on  col2
a     1            1   1.0
b     2            3   2.0
c     3            4   NaN

这不会为索引引入一个虚拟索引名。

但是请注意,这里没有DataFrame。映射方法,因此这种方法不适用于多列。

对于那些想要保持左索引和左连接之前一样的人:

def left_join(
    a: pandas.DataFrame, b: pandas.DataFrame, on: list[str], b_columns: list[str] = None
) -> pandas.DataFrame:
    if b_columns:
        b_columns = set(on + b_columns)
        b = b[b_columns]
    df = (
        a.reset_index()
        .merge(
            b,
            how="left",
            on=on,
        )
        .set_index(keys=[x or "index" for x in a.index.names])
    )
    df.index.names = a.index.names
    return df

另一个简单的选项是将索引重命名为以前的索引:

a.merge(b, how="left").set_axis(a.index)

Merge保留了数据帧“a”的顺序,但只是重置了索引,所以使用set_axis是安全的

df1 = df1.merge(df2, how="inner", left_index=True, right_index=True)

这允许保留df1的索引