【问题标题】:`pandas.merge` not recognising same index`pandas.merge` 不识别相同的索引
【发布时间】:2019-01-14 05:23:11
【问题描述】:

我有两个具有重叠列但索引相同的数据框,我想将它们组合起来。我觉得这应该是直截了当的,但我已经处理了很多示例和 SO 问题,但它不起作用,但似乎与其他示例不一致。

import pandas as pd
# create test data
df = pd.DataFrame({'gen1': [1, 0, 0, 1, 1], 'gen3': [1, 0, 0, 1, 0], 'gen4': [0, 1, 1, 0, 1]}, index = ['a', 'b', 'c', 'd', 'e'])
df1 = pd.DataFrame({'gen1': [1, 0, 0, 1, 1], 'gen2': [0, 1, 1, 1, 1], 'gen3': [1, 0, 0, 1, 0]}, index = ['a', 'b', 'c', 'd', 'e'])

In [1]: df
Out[1]: 
   gen1  gen2  gen3
a     1     0     1
b     0     1     0
c     0     1     0
d     1     1     1
e     1     1     0

In [2]: df1
Out[2]: 
   gen1  gen3  gen4
a     1     1     0
b     0     0     1
c     0     0     1
d     1     1     0
e     1     0     1

在处理完此处 (https://pandas.pydata.org/pandas-docs/stable/merging.html) 的所有示例后,我确信我找到了正确的示例(合并的第一个和第二个示例)。第二个例子是这样的:

In [43]: result = pd.merge(left, right, on=['key1', 'key2'])

在他们的示例中,他们有两个 DF(左和右),它们具有重叠的列和相同的索引,并且它们生成的数据框具有每个列和原始索引的一个版本,但是当我这样做时,情况并非如此:

# get the intersection of columns (I need this to be general)
In [3]: column_intersection = list(set(df).intersection(set(df1))

In [4]: pd.merge(df, df1, on=column_intersection)
Out[4]: 
   gen1  gen2  gen3  gen4
0     1     0     1     0
1     1     0     1     0
2     1     1     1     0
3     1     1     1     0
4     0     1     0     1
5     0     1     0     1
6     0     1     0     1
7     0     1     0     1
8     1     1     0     1

这里我们看到merge没有看到索引是一样的!我摆弄了选项,但无法得到我想要的结果。

在这里How to keep index when using pandas merge 提出了一个类似但不同的问题,但我并不真正理解答案,因此无法将其与我的问题联系起来。

这个具体例子的要点:

  • 索引将始终相同。
  • 具有相同名称的列将始终具有相同的条目(即它们是重复的)。

很高兴为这个特定问题提供解决方案,但我也很想了解它,因为我发现自己不时花费大量时间来组合数据帧。我喜欢 pandas,总的来说,我觉得它非常直观,但除了数据框的琐碎组合之外,我似乎无法适应任何其他事情。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    从 v0.23 开始,您可以为连接键指定索引名称(如果有)。

    df.index.name = df1.index.name = 'idx'
    df.merge(df1, on=list(set(df).intersection(set(df1)) | {'idx'}))
    
         gen1  gen3  gen4  gen2
    idx                        
    a       1     1     0     0
    b       0     0     1     1
    c       0     0     1     1
    d       1     1     0     1
    e       1     0     1     1 
    

    这里的假设是您的实际 DataFrame 在重叠列中没有完全相同的值。如果他们这样做了,那么您的问题将是串联问题之一——您可以使用pd.concat

    c = list(set(df).intersection(set(df1)))
    pd.concat([df1, df.drop(c, 1)], axis=1)
    
         gen1  gen2  gen3  gen4                     
    a       1     0     1     0
    b       0     1     0     1
    c       0     1     0     1
    d       1     1     1     0
    e       1     1     0     1
    

    【讨论】:

    • 感谢@coldspeed,但您的线路df.merge(df1, on=list(set(df).intersection(set(df1)) | {'idx'})) 返回KeyError: 'idx'。索引都命名为“idx”,df['idx'] 是否会返回相同的错误?
    • @ojunk 实际上我认为您的熊猫可能需要更新,这仅适用于最新版本。
    • 是的,你是对的 - 很抱歉你在回答中说我只是忘记了。谢谢!
    【解决方案2】:

    在这种特殊情况下,您可以使用assign
    df 中的内容优先,但 df1 中的所有其他内容都包括在内。

    df1.assign(**df)
    
       gen1  gen2  gen3  gen4
    a     1     0     1     0
    b     0     1     0     1
    c     0     1     0     1
    d     1     1     1     0
    e     1     1     0     1
    

    **df 解包df 假设一个字典上下文。此解包将关键字参数传递给assign,其中列名作为关键字,列作为参数。

    一样
    df1.assign(gen1=df.gen1, gen3=df.gen3, gen4=df.gen4)
    

    【讨论】:

      猜你喜欢
      • 2018-11-07
      • 2018-01-09
      • 1970-01-01
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 2020-02-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多