【问题标题】:How to keep index when using pandas merge使用 pandas 合并时如何保留索引
【发布时间】:2012-08-12 04:09:33
【问题描述】:

我想合并两个DataFrames,并将第一帧的索引作为合并数据集的索引。但是,当我进行合并时,生成的 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')

编辑:切换到可以轻松复制的示例代码

【问题讨论】:

  • 如果在特定列上合并,则不清楚要使用哪些索引(以防它们都不同)。
  • 例如,您是进行左合并还是右合并非常清楚。

标签: python pandas


【解决方案1】:
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

请注意,对于某些左合并操作,当ab 之间存在多个匹配时,您最终可能会得到比a 更多的行。在这种情况下,您可能需要drop duplicates

【讨论】:

  • 非常聪明。 a.merge(b, how="left").set_index(a.index) 也有效,但它似乎不太健壮(因为它的第一部分在重置它们之前将索引值丢失到 a。)
  • 对于这种特殊情况,它们是等价的。但是对于许多合并操作,结果帧的行数与原始a 帧的行数不同。 reset_index 将索引移动到常规列,并且在合并后 set_index 从此列中也注意当 a 的行由于合并操作而被复制/删除时。
  • @Wouter 我很想知道为什么默认情况下左合并会重新索引。我在哪里可以了解更多信息?
  • 不错!为了避免明确指定索引名称,我使用a.reset_index().merge(b, how="left").set_index(a.index.names)
  • Pandas 错误地认为 API 又来了。
【解决方案2】:

有一个使用Series.mapDataFrame.set_index 的非pd.merge 解决方案。

In: a['col2'] = a['to_merge_on'].map(b.set_index('to_merge_on')['col2']))
In: a['col2']
Out:
   col1  to_merge_on  col2
a     1            1   1.0
b     2            3   2.0
c     3            4   NaN

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

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

【讨论】:

  • 这似乎优于公认的答案,因为它可能更适用于多索引等边缘情况。有人可以对此发表评论吗?
  • 问题,如果您需要分配多个列,这种方法会起作用还是仅限于 1 个字段?
  • @Yuca:这可能不适用于多列,因为当您对多列进行子集化时,您最终会得到 pd.Dataframe 而不是 pd.Series.map() 方法仅为pd.Series 定义。这意味着:a[['to_merge_on_1', 'to_merge_on_2']].map(...) 不起作用。
  • 太棒了。在我的项目中,我们到处都使用了太多的 pandas 技巧。这是非常令人耳目一新的,因为它是直截了当的和低水平的。谢谢!
【解决方案3】:
df1 = df1.merge(df2, how="inner", left_index=True, right_index=True)

这允许保留 df1 的索引

【讨论】:

  • 它似乎有效,但是当我将它与on=list_of_cols] 一起使用时,它与文档相矛盾:If joining columns on columns, the DataFrame indexes *will be ignored*。使用索引与列之一是否具有优先权?
【解决方案4】:

您可以在左侧数据框上复制索引并进行合并。

a['copy_index'] = a.index
a.merge(b, how='left')

我发现这个简单的方法在处理大型数据框和使用pd.merge_asof()(或dd.merge_asof())时非常有用。

当重置索引成本高(大数据框)时,这种方法会更好。

【讨论】:

  • 这是最好的答案。您希望在合并期间保留旧索引的原因有很多(并且接受的答案不保留索引,它只是重置它们)。当您尝试合并超过 2 个数据框时,它会有所帮助,等等...
  • 更好的解决方案,因为它保留了(原始)索引名称
  • 赞成,但请注意警告,当使用多索引时,您的索引将作为元组存储在名为 a[copy_index] 的单个列中
  • 我在文档中读到的关于merge_asof 的内容表明它没有使用索引加入,而是使用关闭索引加入。您还必须以某种方式对数据进行排序,以便最近的索引正确连接。
【解决方案5】:

我想我想出了一个不同的解决方案。我在索引值上加入左表,在基于左表索引的列值上加入右表。我所做的是正常的合并:

First10ReviewsJoined = pd.merge(First10Reviews, df, left_index=True, right_on='Line Number')

然后我从合并表中检索到新的索引号,并将它们放在一个名为 Sentiment Line Number 的新列中:

First10ReviewsJoined['Sentiment Line Number']= First10ReviewsJoined.index.tolist()

然后我手动将索引设置回原始的左表索引,该索引基于预先存在的称为行号的列(我从左表索引加入的列值):

First10ReviewsJoined.set_index('Line Number', inplace=True)

然后删除行号的索引名称,使其保持空白:

First10ReviewsJoined.index.name = None

也许有点小技巧,但似乎运作良好且相对简单。此外,猜测它可以降低重复/弄乱数据的风险。希望这一切都有意义。

【讨论】:

    【解决方案6】:

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

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

    merge 保留数据帧“a”处的顺序,但只是重置索引以便保存以使用 set_axis

    【讨论】:

      【解决方案7】:

      假设生成的 df 具有与您的第一个 df 相同的行数和顺序,您可以这样做:

      c = pd.merge(a, b, on='to_merge_on')
      c.set_index(a.index,inplace=True)
      

      【讨论】:

        猜你喜欢
        • 2012-11-14
        • 2013-09-08
        • 2018-11-11
        • 1970-01-01
        • 1970-01-01
        • 2018-01-29
        • 2014-07-28
        • 2019-05-16
        • 2019-07-18
        相关资源
        最近更新 更多