Pandas DataFrame连接表,几种连接方法的对比

Pandas.DataFrame操作表连接有三种方式:merge, join, concat。下面就来说一说这三种方式的特性和用法。

先看两张表:


Screen Shot 2018-08-31 at 2.24.44 PM.png

Screen Shot 2018-08-31 at 2.24.52 PM.png
  1. merge。相当于SQL中的JOIN。该函数的典型应用场景是,两张表有相同内容的列(即SQL中的键),现在我们想把两张表整合到一张表里。在此典型情况下,结果集的行数并没有增加,列数则为两个元数据的列数和减去连接键的数量。

1.1 参数说明:

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)

left与right:两个不同的DataFrame
how:指的是合并(连接)的方式有inner(内连接),left(左外连接),right(右外连接),outer(全外连接);默认为inner!
on : 指的是用于连接的列索引名称。必须存在右右两个DataFrame对象中,如果没有指定且其他参数也未指定则以两个DataFrame的列名交集做为连接键
left_on:左则DataFrame中用作连接键的列名;这个参数中左右列名不相同,但代表的含义相同时非常有用。
right_on:右则DataFrame中用作 连接键的列名
left_index:使用左则DataFrame中的行索引做为连接键,用到这个参数时,就有点类似于接下来要说的JOIN函数了。
right_index:使用右则DataFrame中的行索引做为连接键
sort:默认为True,将合并的数据进行排序。在大多数情况下设置为False可以提高性能
suffixes:字符串值组成的元组,用于指定当左右DataFrame存在相同列名时在列名后面附加的后缀名称,默认为('_x','_y')
copy:默认为True,总是将数据复制到数据结构中;大多数情况下设置为False可以提高性能
indicator:在 0.17.0中还增加了一个显示合并数据中来源情况;如只来自己于左边(left_only)、两者(both)

1.2 merge的特征
1.2.1 默认以重叠列名当做链接键
1.2.2 默认是INNER JOIN。
1.2.3 可以多键连接,'on'参数后传入多键列表即可
1.2.4 如果两个对象的列表不同,可以用left_on, right_on指定。
1.2.5 也可以用行索引当连接键,使用参数left_index=True, right_index=True. 但是这种情况下最好用JOIN

现在来看例子:
开头介绍的两张表除了列名有重叠,内容并没有重叠的地方,所以并不是典型的merge场景。但是,用merge能不能合并呢?也可以。
如果用merge:pd.merge(df1, df2),会得到一张空表
必须指定行索引参数left_index, right_index:

pd.merge(df1, df2, left_index=True, right_index=True, how='left')
Screen Shot 2018-08-31 at 2.30.56 PM.png

这种是「非典型」应用,这种表的场景,更多的时候我们用JOIN函数来实现:

  1. JOIN 拼接列,主要用于基于行索引上的合并。
  • 只要两个表列名不同,不加任何参数就可以直接用。
  • 如果两个表有重复的列名,需指定lsuffix, rsuffix参数。
  • 其中参数的意义与merge方法基本相同,只是join方法默认为左外连接how=left
df1.join(df2, lsuffix='_l', rsuffix='_r') # 列名重复的时候需要指定lsuffix, rsuffix参数
Screen Shot 2018-08-31 at 3.10.52 PM.png

JOIN最适合的情况是基于行索引,上述例子因为列名有重复(即使内容没有重复),所以必须在JOIN的时候设置lsuffix, rsuffix参数,否则会报错。
如果列名不重复,则直接用' df1.join(df2) '即可。

但是! 如果我们想用JOIN实现基于列索引的合并,也是完全可以的。请注意以下的讨论全是关于用JOIN实现列索引合并的,即如何正确使用JOIN函数中的「ON」参数。
用JOIN实现基于列索引的合并主要考虑三种情况:

  • 列名不同,列内容有相同
  • 列名相同,列内容有相同
  • 列名不同,列内容也不同

(1) 列名不同,列内容有相同,需要用到 l.join(r.set_index(key of r), on='key of l')

left = pd.DataFrame({'key1': ['foo', 'bar1'], 'lval': [1, 2]})
right = pd.DataFrame({'key2': ['foo', 'bar'], 'rval': [4, 5]})
left.join(right.set_index('key2'), on='key1')
Screen Shot 2018-08-31 at 4.05.30 PM.png

这种JOIN的写法等同于前面提到的merge设置left_on,right_on。

pd.merge(left, right,left_on='key1', right_on='key2') # 列名不同,但内容有相同可以当键
Screen Shot 2018-08-31 at 4.10.38 PM.png

因为merge默认是内连接,所以返回的结果只有一行,而JOIN返回的结果是以左表的key列为准,有两行。

(2)列名相同,内容有相同,需要用到l.join(r.set_index(key), on='key')。

left = pd.DataFrame({'key': ['foo', 'bar1'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
left.join(right.set_index('key'), on='key',lsuffix='_l', rsuffix='_r')
Screen Shot 2018-08-31 at 4.18.25 PM.png

这种JOIN的写法等同于前面提到的merge设置不带任何参数,而且这种情况下merge会去掉重复的列

pd.merge(left, right) # 列名不同,但内容有相同,所以依然可以作为键来用
Screen Shot 2018-08-31 at 4.20.42 PM.png

同样,因为merge默认是内连接,所以返回的结果只有一行,而JOIN返回的结果是以左表的key列为准,有两行。

特别注意,即使列名相同了,也必须用到' set_index(key)' 否则连接集会显示如下:

left.join(right,on='key',lsuffix='_l', rsuffix='_r')
Screen Shot 2018-08-31 at 4.34.59 PM.png

另外值得注意的一点,不指定'ON= '参数的情况下,JOIN是按行索引连接,也就是简单的水平连接两个表,不对列进行任何操作。如下代码返回的结果:

left.join(right,lsuffix='_l', rsuffix='_r')
Screen Shot 2018-08-31 at 4.25.30 PM.png

这个结果其实和用concat进行行操作是一模一样的:

pd.concat([left, right], axis=1)

(3)列名不同,内容也不同
这种情况是典型的行索引,不能用JOIN的ON参数进行列连接。

  1. concat 轴向连接。就是单纯地把两个表拼在一起,这个过程也被称作绑定(binding)或堆叠(stacking)。因此可以想见,这个函数的关键参数应该是 axis,用于指定连接的轴向。axis=1 在行中操作,axis=0是在列中操作。
    默认是axis=0,即垂直堆叠。
df1=pd.DataFrame(np.random.randn(3,4),columns=['a','b','c','d'])
df2=pd.DataFrame(np.random.randn(2,3),columns=['b','d','a'])
pd.concat([df1, df2], axis=1) # 对行操作,相当于水平连接

注意到这里,左表和右表没有一个单元格是一样的,只是按照行索引水平堆在了一起,所以可以理解为相当于

pd.merge(df1,df2,left_index=True,right_index=True,how='outer') 

或者

df1.join(df2, lsuffix="_l")

效果都是生成这样一张表


Screen Shot 2018-08-31 at 1.24.10 PM.png

最后看看CONCAT的垂直堆叠。垂直堆叠就是axis=0,这种情况下有个参数比较特殊,叫' ignore_index= ',默认情况下是False。如果设成了True,就是把结果的合并表重新编排行索引。否则,行索引还是原来两个表里的值,比如"0,1,2,0,1"

pd.concat([df1, df2], axis=0, ignore_index=True)
Screen Shot 2018-08-31 at 1.26.39 PM.png

如果两张表的列名都不相同,垂直堆叠会生扩展不同的列,生成一张更宽的表。

参考:https://blog.csdn.net/zutsoft/article/details/51498026

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341

推荐阅读更多精彩内容