5个必知必会的 Python 数据合并技巧
Posted Python学习与数据挖掘
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5个必知必会的 Python 数据合并技巧相关的知识,希望对你有一定的参考价值。
大家好,前不久在我们技术交流群有群友提到最近他面试阿里70万总包的数据岗位,对方问Pandas
的5
种数据合并的函数,结果他只答出了2
个。
那么,究竟是哪五个呢?今天,我们就来带大家了解一下!想加技术交流群的,文末获取
目录:
-
1. concat
-
2. append
-
3. merge
-
4. join
-
5. combine
-
总结
1. concat
concat
是pandas
中专门用于数据连接合并的函数,功能非常强大,支持纵向合并和横向合并,默认情况下是纵向合并,具体可以通过参数进行设置。
pd.concat(
objs: 'Iterable[NDFrame] | Mapping[Hashable, NDFrame]',
axis=0,
join='outer',
ignore_index: 'bool' = False,
keys=None,
levels=None,
names=None,
verify_integrity: 'bool' = False,
sort: 'bool' = False,
copy: 'bool' = True,
) -> 'FrameOrSeriesUnion'
在函数方法中,各参数含义如下:
objs
: 用于连接的数据,可以是DataFrame
或Series
组成的列表
axis=0
: 连接的方式,默认为0也就是纵向连接,可选 1 为横向连接
join='outer'
:合并方式,默认为inner
也就是交集,可选outer
为并集
ignore_index
: 是否保留原有的索引
keys=None
:连接关系,使用传递的值作为一级索引
levels=None
:用于构造多级索引
names=None
:索引的名称
verify_integrity
: 检测索引是否重复,如果为True则有重复索引会报错
sort
: 并集合并方式下,对columns排序
copy
: 是否深度拷贝
接下来,我们就对该函数功能进行演示
基础连接
In [1]: import pandas as pd
In [2]: s1 = pd.Series(['a', 'b'])
In [3]: s2 = pd.Series(['c', 'd'])
In [4]: s1
Out[4]:
0 a
1 b
dtype: object
In [5]: s2
Out[5]:
0 c
1 d
dtype: object
In [6]: pd.concat([s1, s2])
Out[6]:
0 a
1 b
0 c
1 d
dtype: object
In [7]: df1 = pd.DataFrame([['a', 1], ['b', 2]],
...: columns=['letter', 'number'])
In [8]: df2 = pd.DataFrame([['c', 3], ['d', 4]],
...: columns=['letter', 'number'])
In [9]: pd.concat([df1, df2])
Out[9]:
letter number
0 a 1
1 b 2
0 c 3
1 d 4
横向连接
In [10]: pd.concat([df1, df2], axis=1)
Out[10]:
letter number letter number
0 a 1 c 3
1 b 2 d 4
默认情况下,concat
是取并集,如果两个数据中有个数据没有对应行或列,则会填充为空值NaN
。
合并交集
In [11]: df3 = pd.DataFrame([['c', 3, 'cat'], ['d', 4, 'dog']],
...: columns=['letter', 'number', 'animal'])
In [12]: df1
Out[12]:
letter number
0 a 1
1 b 2
In [13]: df3
Out[13]:
letter number animal
0 c 3 cat
1 d 4 dog
In [14]: pd.concat([df1, df3], join='inner')
Out[14]:
letter number
0 a 1
1 b 2
0 c 3
1 d 4
索引重置(不保留原有索引)
In [15]: pd.concat([df1, df3], join='inner', ignore_index=True)
Out[15]:
letter number
0 a 1
1 b 2
2 c 3
3 d 4
# 以下方式和上述的输出结果等价
In [16]: pd.concat([df1, df3], join='inner').reset_index(drop=True)
Out[16]:
letter number
0 a 1
1 b 2
2 c 3
3 d 4
指定索引
In [17]: pd.concat([df1, df3], keys=['df1','df3'])
Out[17]:
letter number animal
df1 0 a 1 NaN
1 b 2 NaN
df3 0 c 3 cat
1 d 4 dog
In [18]: pd.concat([df1, df3], keys=['df1','df3'], names=['df名称','行ID'])
Out[18]:
letter number animal
df名称 行ID
df1 0 a 1 NaN
1 b 2 NaN
df3 0 c 3 cat
1 d 4 dog
检测重复
如果索引出现重复,则无法通过检测,会报错
In [19]: pd.concat([df1, df3], verify_integrity=True)
Traceback (most recent call last):
...
ValueError: Indexes have overlapping values: Int64Index([0, 1], dtype='int64')
合并并集下columns排序
In [21]: pd.concat([df1, df3], sort=True)
Out[21]:
animal letter number
0 NaN a 1
1 NaN b 2
0 cat c 3
1 dog d 4
DataFrame与Series合并
In [22]: pd.concat([df1, s1])
Out[22]:
letter number 0
0 a 1.0 NaN
1 b 2.0 NaN
0 NaN NaN a
1 NaN NaN b
In [23]: pd.concat([df1, s1], axis=1)
Out[23]:
letter number 0
0 a 1 a
1 b 2 b
# 新增列一般可选以下两种方式
In [24]: df1.assign(新增列=s1)
Out[24]:
letter number 新增列
0 a 1 a
1 b 2 b
In [25]: df1['新增列'] = s1
In [26]: df1
Out[26]:
letter number 新增列
0 a 1 a
1 b 2 b
以上就concat
函数方法的一些功能,相比之下,另外一个函数append
也可以用于数据追加(纵向合并)
2. append
append
主要用于追加数据,是比较简单直接的数据合并方式。
df.append(
other,
ignore_index: 'bool' = False,
verify_integrity: 'bool' = False,
sort: 'bool' = False,
) -> 'DataFrame'
在函数方法中,各参数含义如下:
other
: 用于追加的数据,可以是DataFrame
或Series
或组成的列表
ignore_index
: 是否保留原有的索引
verify_integrity
: 检测索引是否重复,如果为True则有重复索引会报错
sort
: 并集合并方式下,对columns排序
接下来,我们就对该函数功能进行演示
基础追加
In [41]: df1.append(df2)
Out[41]:
letter number
0 a 1
1 b 2
0 c 3
1 d 4
In [42]: df1.append([df1,df2,df3])
Out[42]:
letter number animal
0 a 1 NaN
1 b 2 NaN
0 a 1 NaN
1 b 2 NaN
0 c 3 NaN
1 d 4 NaN
0 c 3 cat
1 d 4 dog
columns重置(不保留原有索引)
In [43]: df1.append([df1,df2,df3], ignore_index=True)
Out[43]:
letter number animal
0 a 1 NaN
1 b 2 NaN
2 a 1 NaN
3 b 2 NaN
4 c 3 NaN
5 d 4 NaN
6 c 3 cat
7 d 4 dog
检测重复
如果索引出现重复,则无法通过检测,会报错
In [44]: df1.append([df1,df2], verify_integrity=True)
Traceback (most recent call last):
...
ValueError: Indexes have overlapping values: Int64Index([0, 1], dtype='int64')
索引排序
In [46]: df1.append([df1,df2,df3], sort=True)
Out[46]:
animal letter number
0 NaN a 1
1 NaN b 2
0 NaN a 1
1 NaN b 2
0 NaN c 3
1 NaN d 4
0 cat c 3
1 dog d 4
追加Series
In [49]: s = pd.Series('letter':'s1','number':9)
In [50]: s
Out[50]:
letter s1
number 9
dtype: object
In [51]: df1.append(s)
Traceback (most recent call last):
...
TypeError: Can only append a Series if ignore_index=True or if the Series has a name
In [53]: df1.append(s, ignore_index=True)
Out[53]:
letter number
0 a 1
1 b 2
2 s1 9
追加字典
这个在爬虫的时候比较好使,每爬取一条数据就合并到DataFrame
类似数据中存储起来
In [54]: dic = 'letter':'s1','number':9
In [55]: df1.append(dic, ignore_index=True)
Out[55]:
letter number
0 a 1
1 b 2
2 s1 9
3. merge
merge
函数方法类似SQL
里的join
,可以是pd.merge
或者df.merge
,区别就在于后者待合并的数据是
pd.merge(
left: 'DataFrame | Series',
right: 'DataFrame | Series',
how: 'str' = 'inner',
on: 'IndexLabel | None' = None,
left_on: 'IndexLabel | None' = None,
right_on: 'IndexLabel | None' = None,
left_index: 'bool' = False,
right_index: 'bool' = False,
sort: 'bool' = False,
suffixes: 'Suffixes' = ('_x', '_y'),
copy: 'bool' = True,
indicator: 'bool' = False,
validate: 'str | None' = None,
) -> 'DataFrame'
在函数方法中,关键参数含义如下:
left
: 用于连接的左侧数据
right
: 用于连接的右侧数据
how
: 数据连接方式,默认为 inner,可选outer、left和right
on
: 连接关键字段,左右侧数据中需要都存在,否则就用left_on和right_on
left_on
: 左侧数据用于连接的关键字段
right_on
: 右侧数据用于连接的关键字段
left_index
: True表示左侧索引为连接关键字段
right_index
: True表示右侧索引为连接关键字段
suffixes
: ‘Suffixes’ = (’_x’, ‘_y’),可以自由指定,就是同列名合并后列名显示后缀
indicator
: 是否显示合并后某行数据的归属来源
接下来,我们就对该函数功能进行演示
基础合并
In [55]: df1 = pd.DataFrame('key': ['foo', 'bar', 'bal'],
...: 'value2': [1, 2, 3])
In [56]: df2 = pd.DataFrame('key': ['foo', 'bar', 'baz'],
...: 'value1': [5, 6, 7])
In [57]: df1.merge(df2)
Out[57]:
key value2 value1
0 foo 1 5
1 bar 2 6
其他连接方式
In [58]: df1.merge(df2, how='left')
Out[58]:
key value2 value1
0 foo 1 5.0
1 bar 2 6.0
2 bal 3 NaN
In [59]: df1.merge(df2, how='right')
Out[59]:
key value2 value1
0 foo 1.0 5
1 bar 2.0 6
2 baz NaN 7
In [60]: df1.merge(df2, how='outer')
Out[60]:
key value2 value1
0 foo 1.0 5.0
1 bar 2.0 6.0
2 bal 3.0 NaN
3 baz NaN 7.0
In [61]: df1.merge(df2, how='cross')
Out[61]:
key_x value2 key_y value1
0 foo 1 foo 5
1 foo 1 bar 6
2 foo 1 baz 7
3 bar 2 foo 5
4 bar 2 bar 6
5 bar 2 baz 7
6 bal 3 foo 5
7 bal 3 bar 6
8 bal 3 baz 7
指定连接键
可以指定单个连接键,也可以指定多个连接键
In [62]: df1 = pd.DataFrame('lkey1': ['foo', 'bar', 'bal'],
...: 'lkey2': ['a', 'b', 'c'],
...: 'value2': [1, 2, 3])
In [63]: df2 = pd.DataFrame('rkey1': ['foo', 'bar', 'baz'],
...: 'rkey2': ['a', 'b', 'c'],
...: 'value2': [5, 6, 7])
In [64]: df1
Out[64]:
lkey1 lkey2 value2
0 foo a 1
1 bar b 2
2 bal c 3
In [65]: df2
Out[65]:
rkey1 rkey2 value2
0 foo a 5
1 bar b 6
2 baz c 7
In [66]: df1.merge(df2, left_on='lkey1', right_on='rkey1')
Out[66]:
lkey1 lkey2 value2_x rkey1 rkey2 value2_y
0 foo a 1 foo a 5
1 bar b 2 bar b 6
In [67]: df1.merge(df2, left_on=['lkey1','lkey2'], right_on=['rkey1','rkey2'])
Out[67]:
lkey1 lkey2 value2_x rkey1 rkey2 value2_y
0 foo a 1 foo a 5
1 bar b 2 bar b 6
指定索引为键
Out[68]: df1.merge(df2, left_index=True, right_index=True)
Out[68]:
lkey1 lkey2 value2_x rkey1 rkey2 value2_y
0 foo a 1 foo a 5
1 bar b 2 bar b 6
2 bal c 3 baz c 7
设置重复列后缀
In [69]: df1.merge(df2, left_on='lkey1', right_on='rkey1', suffixes=['左','右'])
Out[69]:
lkey1 lkey2 value2左 rkey1 rkey2 value2右
10个必知必会的PyCharm使用技巧