【问题标题】:What is the difference between join and merge in Pandas?Pandas 中的 join 和 merge 有什么区别?
【发布时间】:2014-05-05 17:53:41
【问题描述】:

假设我有两个这样的 DataFrame:

left = pd.DataFrame({'key1': ['foo', 'bar'], 'lval': [1, 2]})

right = pd.DataFrame({'key2': ['foo', 'bar'], 'rval': [4, 5]})

我想合并它们,所以我尝试这样的事情:

pd.merge(left, right, left_on='key1', right_on='key2')

我很高兴

    key1    lval    key2    rval
0   foo     1       foo     4
1   bar     2       bar     5

但我正在尝试使用 join 方法,我一直认为它非常相似。

left.join(right, on=['key1', 'key2'])

我明白了:

//anaconda/lib/python2.7/site-packages/pandas/tools/merge.pyc in _validate_specification(self)
    406             if self.right_index:
    407                 if not ((len(self.left_on) == self.right.index.nlevels)):
--> 408                     raise AssertionError()
    409                 self.right_on = [None] * n
    410         elif self.right_on is not None:

AssertionError: 

我错过了什么?

【问题讨论】:

  • 这里的具体问题是mergeleft的列连接到right的列,这是你想要的,但是join(... on=[...])left的列连接到索引键right,这不是你想要的。有关详细信息,请参阅下面的答案。
  • DataFrame.join() 总是希望将调用者的索引或键(由on 选项指定)与other 的索引相匹配。请记住,连接索引。而 merge() 是一种更通用的方法。
  • 这看起来像是 dfsql 的一个很好的例子 df = dfsql.query('select * from a left join b on a.id = b.id', a=a_df , b=b_df) github.com/mindsdb/dfsql 关于它的完整文章在这里:medium.com/riselab/…

标签: python pandas dataframe join


【解决方案1】:

来自this documentation

pandas 提供了一个单一的功能,合并,作为所有的入口点 DataFrame 对象之间的标准数据库连接操作:

merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)

还有:

DataFrame.join 是组合两列的便捷方法 可能不同索引的 DataFrame 到单个结果中 数据框。这是一个非常基本的例子:这里的数据对齐是开启的 索引(行标签)。可以使用相同的行为来实现 合并加上指示它使用索引的附加参数:

result = pd.merge(left, right, left_index=True, right_index=True,
how='outer')

【讨论】:

    【解决方案2】:

    将其类比为 SQL“Pandas 合并是外/内连接,Pandas 连接是自然连接”。因此,当您在 pandas 中使用合并时,您想指定要使用哪种 sqlish 连接,而当您使用 pandas 连接时,您确实希望有一个匹配的列标签以确保它连接

    【讨论】:

      【解决方案3】:
      • 加入:默认索引(如果有任何相同的列名,那么它会在默认模式下抛出错误,因为你没有定义 lsuffix 或 rsuffix))
      df_1.join(df_2)
      
      • 合并:默认相同的列名(如果没有相同的列名,默认模式下会抛出错误)
      df_1.merge(df_2)
      
      • on 参数在两种情况下的含义不同
      df_1.merge(df_2, on='column_1')
      
      df_1.join(df_2, on='column_1') // It will throw error
      df_1.join(df_2.set_index('column_1'), on='column_1')
      

      【讨论】:

        【解决方案4】:

        其中一个区别是merge 正在创建一个新索引,而join 正在保留左侧索引。如果您错误地假设您的索引没有被merge 更改,它可能会对您以后的转换产生重大影响。

        例如:

        import pandas as pd
        
        df1 = pd.DataFrame({'org_index': [101, 102, 103, 104],
                            'date': [201801, 201801, 201802, 201802],
                            'val': [1, 2, 3, 4]}, index=[101, 102, 103, 104])
        df1
        
               date  org_index  val
        101  201801        101    1
        102  201801        102    2
        103  201802        103    3
        104  201802        104    4
        

        -

        df2 = pd.DataFrame({'date': [201801, 201802], 'dateval': ['A', 'B']}).set_index('date')
        df2
        
               dateval
        date          
        201801       A
        201802       B
        

        -

        df1.merge(df2, on='date')
        
             date  org_index  val dateval
        0  201801        101    1       A
        1  201801        102    2       A
        2  201802        103    3       B
        3  201802        104    4       B
        

        -

        df1.join(df2, on='date')
               date  org_index  val dateval
        101  201801        101    1       A
        102  201801        102    2       A
        103  201802        103    3       B
        104  201802        104    4       B
        

        【讨论】:

        • 没错。如果我们在索引以外的列上合并两个数据帧,我们将得到一个新索引,但如果我们在两个数据帧的索引上合并,我们将得到一个具有相同索引的数据帧。因此,为了在合并后获得相同的索引,我们可以将列作为两个数据帧的索引(我们要在其上合并),然后在新创建的索引上合并数据帧。
        • 非常有见地。我从来不需要索引(我通常只是重置索引),但这在某些情况下可能会有很大的不同。
        【解决方案5】:

        pandas.merge() 是用于所有合并/连接行为的底层函数。

        DataFrames 提供pandas.DataFrame.merge()pandas.DataFrame.join() 方法作为访问pandas.merge() 功能的便捷方式。例如,df1.merge(right=df2, ...) 等价于 pandas.merge(left=df1, right=df2, ...)

        这些是df.join()df.merge() 之间的主要区别:

        1. 在右表上查找:df1.join(df2) 总是通过df2 的索引连接,但df1.merge(df2) 可以连接到df2(默认)的一个或多个列或df2 的索引(使用@ 987654335@)。
        2. 左表查找:默认情况下,df1.join(df2) 使用df1 的索引,df1.merge(df2) 使用df1 的列。这可以通过指定df1.join(df2, on=key_or_keys)df1.merge(df2, left_index=True) 来覆盖。
        3. 左与内连接:df1.join(df2) 默认执行左连接(保留df1 的所有行),但df.merge 默认执行内连接(仅返回匹配的df1df2 行)。

        因此,通用方法是使用pandas.merge(df1, df2)df1.merge(df2)。但是对于一些常见情况(保留df1 的所有行并加入df2 中的索引),您可以改用df1.join(df2) 来节省一些输入。

        http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging 的文档中关于这些问题的一些说明:

        merge 是 pandas 命名空间中的一个函数,它也是 可作为 DataFrame 实例方法使用,调用 DataFrame 被隐式认为是连接中的左对象。

        相关的DataFrame.join方法,内部使用merge index-on-index 和 index-on-column(s) 连接,但通过索引连接 默认而不是尝试加入公共列(默认 merge) 的行为。如果您要加入索引,您可能希望 使用DataFrame.join 可以节省一些打字时间。

        ...

        这两个函数调用是完全等价的:

        left.join(right, on=key_or_keys)
        pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)
        

        【讨论】:

        • 这绝对应该是公认的答案!感谢您的详尽解释
        • @Matthias Fripp,也许对于更有经验的人来说这是不言而喻的,但也可以说“在右表上查找:df1.join(df2) 可以覆盖为 df1.join(df2 , on=key_or_keys?
        • @spacedustpi,我想你是说你可以使用on=key_or_keys 来改变在右表中找到行的方式。然而,事实并非如此。 on 参数将 left 表 (df1) 上的查找从索引更改为列。然而,即使有这个参数,正确的表 (df2) 也将通过它的索引来匹配。 (请参见上面的最后一个示例。)
        • Pandas 有几种方法来处理这些情况,其中包括 merge、join、append、concat、combine、combine_first。看看这些,看看哪一个最适合你的情况
        【解决方案6】:

        我总是在索引上使用join

        import pandas as pd
        left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]}).set_index('key')
        right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]}).set_index('key')
        left.join(right, lsuffix='_l', rsuffix='_r')
        
             val_l  val_r
        key            
        foo      1      4
        bar      2      5
        

        在以下列上使用merge 可以获得相同的功能:

        left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]})
        right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]})
        left.merge(right, on=('key'), suffixes=('_l', '_r'))
        
           key  val_l  val_r
        0  foo      1      4
        1  bar      2      5
        

        【讨论】:

        • 错误似乎是说它期望right 上的多索引与on 上的长度相同。这对我来说有点道理。我可以接受语义不同。但我想知道是否可以使用 df.join 获得相同的行为
        【解决方案7】:

        我相信join() 只是一种方便的方法。改用df1.merge(df2),它允许您指定left_onright_on

        In [30]: left.merge(right, left_on="key1", right_on="key2")
        Out[30]: 
          key1  lval key2  rval
        0  foo     1  foo     4
        1  bar     2  bar     5
        

        【讨论】:

          猜你喜欢
          • 2011-10-07
          • 2020-07-16
          • 2012-02-22
          • 2016-11-10
          • 2010-09-07
          相关资源
          最近更新 更多