【问题标题】:Difference(s) between merge() and concat() in pandaspandas 中 merge() 和 concat() 的区别
【发布时间】:2016-11-10 09:35:38
【问题描述】:

pd.DataFrame.merge()pd.concat() 的本质区别是什么?

到目前为止,这是我发现的,请评论我的理解有多完整和准确:

  • .merge() 只能使用列(加上行索引),它在语义上适用于数据库样式的操作。 .concat() 可以与任一轴一起使用,仅使用索引,并提供添加分层索引的选项。

  • 顺便说一句,这允许以下冗余:两者都可以使用行索引组合两个数据帧。

  • pd.DataFrame.join() 只是为.merge() 的一部分用例提供简写形式

(Pandas 擅长处理数据分析中非常广泛的用例。探索文档以找出执行特定任务的最佳方法可能有点令人生畏。)

【问题讨论】:

  • 另外,相关:stackoverflow.com/a/37891437/1972495 围绕.merge().join() 展开讨论。
  • 在合并、加入和连接时,我发现this 的回答非常清楚它们如何用于做同样的事情(它们似乎只是相同功能的替代接口)。感谢您的问题(以及您在评论中链接的答案),我终于知道合并和加入是如何相关的。我仍然不清楚 concat 是否使用不同的实现(我想我将不得不查看源代码......)

标签: python pandas join merge concat


【解决方案1】:

一个非常高层次的区别是merge()用于根据公共列的值组合两个(或更多)数据帧(也可以使用索引,使用left_index=True和/或right_index=True),而concat() 用于将一个(或多个)数据帧附加在另一个下方(或横向附加,具体取决于axis 选项设置为0 还是1)。

join()用于在索引的基础上合并2个dataframe;我们可以使用join(),而不是使用merge()left_index=True 选项。

例如:

df1 = pd.DataFrame({'Key': ['b', 'b', 'a', 'c', 'a', 'a', 'b'], 'data1': range(7)})

df1:
   Key  data1
0   b   0
1   b   1
2   a   2
3   c   3
4   a   4
5   a   5
6   b   6

df2 = pd.DataFrame({'Key': ['a', 'b', 'd'], 'data2': range(3)})

df2:
    Key data2
0   a   0
1   b   1
2   d   2

#Merge
# The 2 dataframes are merged on the basis of values in column "Key" as it is 
# a common column in 2 dataframes

pd.merge(df1, df2)

   Key data1 data2
0   b    0    1
1   b    1    1
2   b    6    1
3   a    2    0
4   a    4    0
5   a    5    0

#Concat
# df2 dataframe is appended at the bottom of df1 

pd.concat([df1, df2])

   Key data1 data2
0   b   0     NaN
1   b   1     NaN
2   a   2     NaN
3   c   3     NaN
4   a   4     NaN
5   a   5     NaN
6   b   6     NaN
0   a   Nan   0
1   b   Nan   1
2   d   Nan   2

【讨论】:

  • 所以,这意味着merge 中的参数howconcat 中的参数完全不同?
【解决方案2】:

在高层次上:

  • .concat() 只是将多个 DataFrame 堆叠在一起 垂直,或在索引上对齐后水平缝合
  • .merge() 首先对齐两个 DataFrame' 选定的公共列或 索引,然后从每个 DataFrame 的对齐行中选取剩余的列。

更具体地说,.concat()

  • 是一个顶级的 pandas 函数
  • 组合两个或多个 pandas DataFrame 垂直或水平
  • 水平组合时仅在索引上对齐
  • 当任何DataFrame 包含重复索引时出错。
  • 默认为带有内部联接选项的外部联接

还有.merge()

  • 作为顶级 pandas 函数和 DataFrame 方法存在(自 pandas 1.0 起)
  • 水平组合两个DataFrame
  • 将调用DataFrame 的列或索引与另一个对齐 DataFrame 的列或索引
  • 处理连接列或索引上的重复值 执行笛卡尔积
  • 默认为内连接,带有左、外和右选项

请注意,在执行pd.merge(left, right) 时,如果left 有两行包含来自连接列或索引的相同值,则每行将与right 的相应行组合,从而产生笛卡尔积。另一方面,如果.concat()用于合并列,我们需要确保DataFrame中不存在重复索引。

实际上:

  • 在组合齐次DataFrame 时首先考虑.concat(),而 在组合互补的DataFrame 时首先考虑.merge()
  • 如果需要垂直合并,请使用.concat()。如果需要合并 水平通过列,使用.merge(),默认情况下合并到共同的列上。

参考:Pandas 1.x Cookbook

【讨论】:

    【解决方案3】:

    pd.concatIterable 作为其参数。因此,它不能直接将DataFrames 作为其参数。此外,DataFrameDimensions 应该在连接时沿轴匹配。

    pd.merge 可以将DataFrames 作为其参数,用于将两个具有相同列或索引的DataFrames 组合在一起,而pd.concat 则无法做到这一点,因为它会显示重复的列数据框。

    而 join 可用于连接具有不同索引的两个 DataFrames。

    【讨论】:

    • 我喜欢这个答案,因为它说明连接时尺寸应该匹配。 concat 只不过是将几个数据框粘在彼此的顶部/旁边。它不是内容感知,因为它只会显示同一列两次。而merge 实际上会在它们相同时合并列。
    • 我认为这不是真的。甚至上面的答案(@Abhishek Sawant)也给出了一个尺寸不匹配的concat 示例。
    【解决方案4】:

    我目前正在尝试了解pd.DataFrame.merge()pd.concat() 之间的本质区别。

    好问题。主要区别:

    pd.concat 适用于两个轴。

    另一个区别是 pd.concat 具有 innerdefaultouter 只加入,而 pd.DataFrame.merge()leftright 外层内层默认 加入。

    第三个值得注意的区别是:pd.DataFrame.merge() 可以在合并同名列时设置列后缀,而对于 pd.concat,这是不可能的。


    使用pd.concat 默认情况下,您可以堆叠多个数据帧的行 (axis=0),当您设​​置 axis=1 时,您可以模仿 pd.DataFrame.merge() 函数。

    pd.concat的一些有用的例子:

    df2=pd.concat([df]*2, ignore_index=True) #double the rows of a dataframe
    
    df2=pd.concat([df, df.iloc[[0]]]) # add first row to the end
    
    df3=pd.concat([df1,df2], join='inner', ignore_index=True) # concat two df's
    

    【讨论】:

    【解决方案5】:

    merge 和 concat 之间的主要区别在于,merge 允许您对表执行更结构化的“连接”,其中 concat 的使用范围更广,结构更少。

    合并

    引用documentationpd.DataFrame.mergeright作为必填参数,你可以认为它是根据一些预定义的结构化连接操作来连接左表和右表。注意参数right的定义。

    必需参数

    • :DataFrame 或命名系列

    可选参数

    • 如何:{‘left’, ‘right’, ‘outer’, ‘inner’} 默认‘inner’
    • on:标签或列表
    • left_on:标签或列表,或类似数组
    • right_on:标签或列表,或类数组
    • left_index: bool,默认为 False
    • right_index: bool,默认为 False
    • 排序:bool,默认为False
    • 后缀:元组 (str, str),默认 (‘_x’, ‘_y’)
    • 复制:bool,默认为真
    • 指标:bool或str,默认False
    • 验证:str,可选

    重要提示: pd.DataFrame.merge 要求权限为 pd.DataFrame 或命名为 pd.Series 对象。

    输出

    • 返回:数据帧

    此外,如果我们检查一下关于 Pandas 的 Merge Operation 的文档字符串如下:

    在两个 DataFrame 或 Series 之间执行数据库 (SQL) 合并操作 使用列作为键或其行索引的对象

    连接

    参考pd.concatdocumentation,首先注意参数不是table、data_frame、series、matrix等中的任何一个,而是objs反而。也就是可以传递很多“数据容器”,定义为:

    Iterable[FrameOrSeriesUnion], Mapping[Optional[Hashable], FrameOrSeriesUnion]

    必需参数

    • objs:Series 或 DataFrame 对象的序列或映射

    可选参数

    • :{0/'index', 1/'columns'},默认 0
    • 加入:{‘inner’, ‘outer’},默认‘outer’
    • ignore_index: bool,默认为 False
    • keys:序列,默认无
    • levels:序列列表,默认无
    • 名称:列表,默认无
    • verify_integrity: bool,默认为 False
    • 排序:bool,默认为False
    • 复制:bool,默认为真

    输出

    • 返回:对象,objs的类型

    示例

    代码

    import pandas as pd
    
    v1 = pd.Series([1, 5, 9, 13])
    v2 = pd.Series([10, 100, 1000, 10000])
    v3 = pd.Series([0, 1, 2, 3])
    
    df_left = pd.DataFrame({
        "v1": v1,
        "v2": v2,
        "v3": v3
        })
    df_right = pd.DataFrame({
        "v4": [5, 5, 5, 5],
        "v5": [3, 2, 1, 0]
        })
    
    
    df_concat = pd.concat([v1, v2, v3])
    
    # Performing operations on default
    
    merge_result = df_left.merge(df_right, left_index=True, right_index=True)
    concat_result = pd.concat([df_left, df_right], sort=False)
    print(merge_result)
    print('='*20)
    print(concat_result)
    

    代码输出

       v1     v2  v3  v4  v5
    0   1     10   0   5   3
    1   5    100   1   5   2
    2   9   1000   2   5   1
    3  13  10000   3   5   0
    ====================
         v1       v2   v3   v4   v5
    0   1.0     10.0  0.0  NaN  NaN
    1   5.0    100.0  1.0  NaN  NaN
    2   9.0   1000.0  2.0  NaN  NaN
    3  13.0  10000.0  3.0  NaN  NaN
    0   NaN      NaN  NaN  5.0  3.0
    1   NaN      NaN  NaN  5.0  2.0
    2   NaN      NaN  NaN  5.0  1.0
    

    但是,您可以通过更改 axis 参数来使用 concat 实现第一个输出(合并)

    concat_result = pd.concat([df_left, df_right], sort=False, axis=1)
    

    观察以下行为,

    concat_result = pd.concat([df_left, df_right, df_left, df_right], sort=False)
    

    输出;

         v1       v2   v3   v4   v5
    0   1.0     10.0  0.0  NaN  NaN
    1   5.0    100.0  1.0  NaN  NaN
    2   9.0   1000.0  2.0  NaN  NaN
    3  13.0  10000.0  3.0  NaN  NaN
    0   NaN      NaN  NaN  5.0  3.0
    1   NaN      NaN  NaN  5.0  2.0
    2   NaN      NaN  NaN  5.0  1.0
    3   NaN      NaN  NaN  5.0  0.0
    0   1.0     10.0  0.0  NaN  NaN
    1   5.0    100.0  1.0  NaN  NaN
    2   9.0   1000.0  2.0  NaN  NaN
    3  13.0  10000.0  3.0  NaN  NaN
    0   NaN      NaN  NaN  5.0  3.0
    1   NaN      NaN  NaN  5.0  2.0
    2   NaN      NaN  NaN  5.0  1.0
    3   NaN      NaN  NaN  5.0  0.0
    

    ,您不能使用合并执行类似的操作,因为它只允许单个 DataFrame 或命名的系列。

    merge_result = df_left.merge([df_right, df_left, df_right], left_index=True, right_index=True)
    

    输出;

    TypeError: Can only merge Series or DataFrame objects, a <class 'list'> was passed
    

    结论

    您可能已经注意到,“merge”和“concat”之间的输入和输出可能不同。

    正如我在开头提到的,第一个(主要)区别是“合并”执行更结构化的连接,其中包含一组受限制的对象和参数,而“concat”执行不那么严格/更广泛的连接与更广泛的对象和参数集。

    总而言之,merge 对更改/(输入)的容忍度较低,而“concat”对更改/(输入)更宽松/不太敏感。 你可以通过使用“concat”来实现“merge”,但反过来并不总是如此。

    “合并”操作使用数据框列(或 pd.Series 对象的名称)或行索引,由于它仅使用这些实体,因此它执行数据框或系列的水平合并,因此不应用垂直操作.

    如果你想看更多,你可以深入研究一下源代码;

    【讨论】:

      【解决方案6】:

      只有 concat 函数有轴参数。合并用于根据共享列中的值并排组合数据框,因此不需要轴参数。

      【讨论】:

        【解决方案7】:

        默认情况下:
        join 是按列的左连接
        pd.merge 是按列的内连接
        pd.concat 是逐行外连接

        pd.concat:
        接受可迭代的参数。因此,它不能直接采用 DataFrame(使用 [df,df2])
        DataFrame 的尺寸应沿轴匹配

        加入和 pd.merge:
        可以接受 DataFrame 参数

        Click to see picture for understanding why code below does the same thing

        df1.join(df2)
        pd.merge(df1, df2, left_index=True, right_index=True)
        pd.concat([df1, df2], axis=1)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-05-05
          • 1970-01-01
          • 2017-11-18
          • 1970-01-01
          • 1970-01-01
          • 2019-09-16
          • 1970-01-01
          相关资源
          最近更新 更多