熊猫中merge()和concat()之间的差异


85

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

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

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

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

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

(Pandas非常擅长解决数据分析中的各种用例。探索文档以找出执行特定任务的最佳方法可能有些艰巨。)


3
另外,相关内容:stackoverflow.com/a/37891437/1972495关于.merge()和的讨论.join()
WindChimes '16

2
在merge,join和concat上,我发现这个答案非常清楚,说明它们如何用于完成相同的工作(它们似乎只是相同功能的替代接口)。多亏了您的问题(以及您在评论中链接的答案),我终于了解了合并和联接之间的关系。我仍然不清楚concat是否使用其他实现(我想我将不得不看源代码...)
pietroppeter

Answers:


77

一个非常高的差异是,merge()它用于基于公共列的值组合两个(或多个)数据帧(索引也可以使用,使用left_index=True和/或right_index=True),并concat()用于附加一个(或多个)数据帧下方(或横向放置,取决于该axis选项是设置为0还是1)。

join()用于根据索引合并2个数据帧;而不是使用merge()选项,left_index=True我们可以使用join()

例如:

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

因此,这意味着工作中的论点howmerge工作中的论点完全不同concat
Hemanth Bakaya

11

pd.concat以aIterable为参数。因此,它不能DataFrame直接将s作为其参数。另外DimensionS的的DataFrame同时,串联沿轴线应该匹配。

pd.merge可以将DataFrames作为其参数,并用于将两个DataFrame具有相同列或索引的s组合在一起,因此无法实现,pd.concat因为它将在DataFrame中显示重复的列。

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


7
我喜欢这个答案,因为它指出级联时尺寸应该匹配。concat无非就是将几个数据帧相互之间粘合在一起。从某种意义上说它只会显示两次相同的列,因此它并不满足于内容。而merge实际上,当它们相同时,它们将合并列。
jorijnsmit

2
我认为这是不对的。甚至上面的答案(@Abhishek Sawant)也给出了concat尺寸不匹配的示例。
michcio1234

7

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

好问题。主要区别:

pd.concat 在两个轴上均有效。

另一个区别是,仅pd.concat具有内部默认联接和外部联接,而pd.DataFrame.merge()具有leftright外部内部默认联接。

第三个值得注意的其他区别是:pd.DataFrame.merge()合并具有相同名称的列时,可以选择设置列后缀,但是pd.concat这是不可能的。


随着pd.concat在默认情况下,你都能够堆叠多个dataframes(行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

高层次:

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

更具体地说,.concat()

  • 是顶级熊猫功能
  • DataFrame 垂直或水平组合两个或更多熊猫
  • 水平合并时仅在索引上对齐
  • 当任何一个DataFrame包含重复索引时发生错误。
  • 默认为外部联接,带有内部联接选项

.merge()

  • 作为顶级熊猫函数和DataFrame方法同时存在(自熊猫1.0起)
  • DataFrame水平准确地合并两个
  • 将调用方DataFrame的列或索引与其他DataFrame列或索引 对齐
  • 通过执行笛卡尔乘积来处理联接列或索引上的重复值
  • 默认为内部联接,带有左,外和右选项

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

实际上来说:

  • 考虑.concat()混合均匀时,首先DataFrame,在考虑.merge()合并时,互补第一DataFrame
  • 如果需要垂直合并,请使用.concat()。如果需要通过列水平合并,请使用.merge(),默认情况下,它们会在列上合并。

参考:《Pandas 1.x食谱》


2

merge&concat之间的主要区别在于,merge使您可以在concat的使用范围更广且结构化程度更低的表上执行结构化的“联接”。

合并

引用文档pd.DataFrame.mergeright作为必需的参数,您可以将其视为根据一些预定义的结构化联接操作联接左表和右表。注意参数right的定义。

必要参数

  • :DataFrame或命名的Series

可选参数

  • 方式:{'左','右','外','内'}默认'内'
  • :标签或列表
  • left_on:标签或列表,或类似数组
  • right_on:标签或列表,或类似数组
  • left_index:布尔值,默认为False
  • right_index:布尔值,默认为False
  • 排序:布尔值,默认为False
  • 后缀:(str,str)的元组,默认('_x','_y')
  • 复制:bool,默认为True
  • 指标:bool或str,默认为False
  • validate:str,可选

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

输出量

  • 返回:DataFrame

此外,如果我们在下面检查熊猫的合并操作的文档字符串,请执行以下操作:

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

康卡特

请参阅文件pd.concat,首先要注意的参数中指定的任何的表,data_frame,系列,矩阵等,但OBJ文件来代替。也就是说,您可以传递许多“数据容器”,它们定义为:

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

必要参数

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

可选参数

  • :{0 /'索引',1 /'列'},默认0
  • join:{'inner','outer'},默认为'outer'
  • ignore_index:布尔值,默认为False
  • :序列,默认无
  • 级别:序列列表,默认为无
  • 名称:列表,默认无
  • verify_integrity:bool,默认为False
  • 排序:布尔值,默认为False
  • 复制:bool,默认为True

输出量

  • 返回:对象,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或命名的Series。

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

结论

您可能已经注意到,“合并”和“合并”之间的输入和输出可能有所不同。

正如我在开始时提到的,第一个(主要)区别是“合并”使用一组受限的对象和参数执行更结构化的联接,而“ concat”执行较不严格/较广泛的联接对象和参数。

总而言之,合并对更改/(输入)的容忍度较低,而“ concat”对更改/(输入)的容忍度较低/较不敏感。您可以使用“ concat”来实现“合并”,但并非总是如此。

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

如果您想了解更多,可以稍微深入一下源代码。


-2

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

pd.concat:
采用Iterable参数。因此,它不能直接获取DataFrame(使用[df,df2])
。DataFrame的尺寸应沿轴方向匹配

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

单击以查看图片以了解下面的代码为什么做同样的事情

df1.join(df2)
pd.merge(df1, df2, left_index=True, right_index=True)
pd.concat([df1, df2], axis=1)
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.