pandas中DataFrame的数据堆叠、连接、重塑
A B v1 v2# 内连接print(df3)解析:on=['A','B'] 即将 A、B 列作为连接键,当这个组合键相同时,进行连接,上面的 df1 和 df2 只有索引为2的一行数据是相同的,为 [B,b],因此,在有多列时,需要满足这几列都相同的数据才会进行连接此外,由于merge需指定连接的列,在两个 df没有相同列需要用到索引时(见下方基于索引),应指定left_on、right_on
这里是数据合并与连接的几种方法,分别为 merge、join、concat 和 append
目录
1.基于列使用 how=' ' 定义连接方法,并使用 on=' column_name' 作为连接键
一、连接列:
(一)merge
merge:默认基于共同列或基于索引进行横向连接,操作类似数据库使用 sql 将两张表合并成一张表
语法:merge(left/right, how=‘inner’, on=None, left_on=None, right_on=None, left_index=False, right_index=False, indicator=False)
几个主要参数:
- left,right:要merge的dataframe或者有名字的Series
- how:连接的类型,‘left’,‘right’,‘outer’,‘inner’,默认内连接
- on:join的key,要求left和right都需要有这个key才能用on,如果两个dataframe的列不一样,则用下面两个参数指定
- left_on/right_on:在列名不同时,指定 left/right 的 df 或者 series 的 key
- left_index,right_index:默认FALSE,设置为TRUE会使用 index,而不是column做连接
- indicator:显示合并数据中数据的来源情况,为True时,它会自动给结果加一列“_merge",内容为right_only、left_only、both等,可用于数据的筛选和操作
- sort:默认为True,将合并的数据进行排序,设置为False可以提高性能;
- suffixes:字符串值组成的元组,用于指定当左右 DataFrame 存在相同列名时在列名后面附加的后缀名称,默认为('_x', '_y'),在两表有同名列又均想保留的情况可以使用;
1.基于列使用 how=' ' 定义连接方法,并使用 on=' column_name' 作为连接键
df1 = pd.DataFrame({'A':['A','B','B','C','D','E'],
'B':['a','a','b','c','c','e'],
'v1':[1,1,2,3,3,1],
'v2':['low','medium','medium','high','low','high']})
A B v1 v2
0 A a 1 low
1 B a 1 medium
2 B b 2 medium
3 C c 3 high
4 D c 3 low
5 E e 1 high
df2 = pd.DataFrame({'A':['A','A','B','F'],
'B':['d','d','b','f'],
'F':['apple','orange','peach','pear'],
'Level':['high','low','high','medium'],
'price':np.array([5,6,7,8])})
A B F Level price
0 A d apple high 5
1 A d orange low 6
2 B b peach high 7
3 F f pear medium 8
# 内连接
df3 = pd.merge(df1,df2,on=['A','B'],how='inner')
print(df3)
A B v1 v2 F Level price
0 B b 2 medium peach high 7
解析:on=['A','B'] 即将 A、B 列作为连接键,当这个组合键相同时,进行连接,上面的 df1 和 df2 只有索引为2的一行数据是相同的,为 [B,b],因此,在有多列时,需要满足这几列都相同的数据才会进行连接
此外,由于merge需指定连接的列,在两个 df 没有相同列需要用到索引时(见下方基于索引),应指定left_on、right_on 参数,否则会报错
merge亦可进行纵向的列拼接,但一般来说我们有更好的方法
2.基于索引
-
left_on=' '+right_index=TRUE(右边的索引与左边的列值匹配)
-
right_on' '+left_index=TRUE(左边的索引与右边的列值匹配)
-
left_index=True+right_index=True(左右索引匹配)
# df1
df1 = pd.DataFrame({'A':['A','B','B','C','D','E'],
'B':['a','a','b','c','c','e'],
'v1':[1,1,2,3,3,1],
'v2':['low','medium','medium','high','low','high']})
A B v1 v2
0 A a 1 low
1 B a 1 medium
2 B b 2 medium
3 C c 3 high
4 D c 3 low
5 E e 1 high
# df2
df2 = pd.DataFrame({'A':['A','A','B','F'],
'B':['d','d','b','f'],
'F':['apple','orange','peach','pear'],
'Level':['high','low','high','medium'],
'price':np.array([5,6,7,8])})
A B F Level price
0 A d apple high 5
1 A d orange low 6
2 B b peach high 7
3 F f pear medium 8
# 连接
# 左边的 index 与右边的 price 匹配
df7 = pd.merge(df1,df2,left_index=True,right_on='price')
A_x B_x v1 v2 A_y B_y F Level price
0 E e 1 high A d apple high 5
(二)join
join 和 merge 有相同的作用,不过 join 连接时默认使用行 index 进行连接,可以连接多个 DataFrame,而merge只能连接两个,并且 join 默认使用左外连接
join 的参数与 merge 类似,主要有on、how、suffixes,但没有 left_on/right_on,参数 on 已经指定了作为索引的列,且必须是被匹配的 DataFrame 中存在列:
df1 = pd.DataFrame({'A':['A','B','B','C','D','E'],
'B':['a','a','b','c','c','e'],
'v1':[1,1,2,3,3,1],
'v2':['low','medium','medium','high','low','high']})
df2 = pd.DataFrame({'A':['A','A','B','F'],
'B':['d','d','b','f'],
'F':['apple','orange','peach','pear'],
'Level':['high','low','high','medium'],
'price':np.array([3,4,5,6])})
print(df1)
print('-----------------')
print(df2)
A B v1 v2
0 A a 1 low
1 B a 1 medium
2 B b 2 medium
3 C c 3 high
4 D c 3 low
5 E e 1 high
-----------------
A B F Level price
0 A d apple high 3
1 A d orange low 4
2 B b peach high 5
3 F f pear medium 6
# 左连接
df3=df1.join(df2.set_index('A'),on='A',how='inner',rsuffix='*')
df3
# A,B列同名,需要区分,将 df2 的列加上'*'号后缀
# 这里将df1的 A 列作为索引与 df2 的 A 列匹配
A B v1 v2 B* F Level price
0 A a 1 low d apple high 3.0
0 A a 1 low d orange low 4.0
1 B a 1 medium b peach high 5.0
2 B b 2 medium b peach high 5.0
3 C c 3 high NaN NaN NaN NaN
4 D c 3 low NaN NaN NaN NaN
5 E e 1 high NaN NaN NaN NaN
join 可类似 merge 使用列标签连表,但该函数默认用左表的 on 列和右表的索引进行匹配,因此需要使用 df.set_index(' ').join() 指定某列作为索引
(三)concat
将下方 concat() 中 axis 参数设为 1 即可
二、连接行
(一)concat
如下两个dataframe
df1 = pd.DataFrame({'A':['A','B','B','C','D','E'],
'B':['a','a','b','c','c','e'],
'v1':[1,1,2,3,3,1],
'v2':['low','medium','medium','high','low','high']})
A B v1 v2
0 A a 1 low
1 B a 1 medium
2 B b 2 medium
3 C c 3 high
4 D c 3 low
5 E e 1 high
df2 = pd.DataFrame({'A':['A','A','B','F'],
'B':['d','d','b','f'],
'F':['apple','orange','peach','pear'],
'Level':['high','low','high','medium'],
'price':np.array([3,4,5,6])})
A B F Level price
0 A d apple high 3
1 A d orange low 4
2 B b peach high 5
3 F f pear medium 6
concat 既可以进行纵向连接也可以进行横向连接,默认 axis=0 ,join='outer' 连接行的全外连接,在做行拼接时,行索引可以重复,列索引根据连接方式而定(outer 或 inner取并/交集),列拼接可由此类比
语法:pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None, levels=None, names=None, verify_integrity=False, sort=None, copy=True)
- objs:要拼接的对象,以列表形式传入
- axis:0表示纵向拼接行,1表示横向拼接列
- join:连接方式
- ignore_index:默认False,即按照原来索引排序,设为True时忽略索引从1开始逐渐递增
df3=pd.concat([df1,df2],axis=0,join='inner',ignore_index=True,)
print(df3)
A B
0 A a
1 B a
2 B b
3 C c
4 D c
5 E e
6 A d
7 A d
8 B b
9 F f
- keys:可以是任意值的列表或数组、元组数组、数组列表,与 objs 对应可以进行表的溯源,也可以在有重复索引时做层次化索引(ignore_index优先生效)
df3=pd.concat([df1,df2],keys=['one','two'],axis=0,join='inner')
print(df3)
A B
one 0 A a
1 B a
2 B b
3 C c
4 D c
5 E e
two 0 A d
1 A d
2 B b
3 F f
(二)append
语法:dt._append(dt2,ignore_index=False,verify_integrity=False)
append 属于简化版的concat,只能在 axis=0 方向上合并,即只能纵向拼接列,了解一下即可
- ignore_index:默认False,这样行索引保持与原DataFrame中的行索引一致,即行索引重复不会受影响。若修改为True,结果的行索引会被重设为从0开始的整数索引。
- verify_integrity:是否允许有重复标签默认False,添加的DataFrame中有相同的行索引时,可以保留原结果。若该参数为True,添加的新 DataFrame 中有相同的行索引时就会抛出ValueError报错。该参数设置为True可以避免结果中的行索引重复,但可能会导致添加失败,所以需要先观察原始数据。
以上两个参数同时使用并不会报错,ignore_index 优先生效
df1 = pd.DataFrame({'A':['A','B','B','C','D','E'],
'B':['a','a','b','c','c','e'],
'v1':[1,1,2,3,3,1],
'v2':['low','medium','medium','high','low','high']})
A B v1 v2
0 A a 1 low
1 B a 1 medium
2 B b 2 medium
3 C c 3 high
4 D c 3 low
5 E e 1 high
df2 = pd.DataFrame({'A':['A','A','B','F'],
'B':['d','d','b','f'],
'F':['apple','orange','peach','pear'],
'Level':['high','low','high','medium'],
'price':np.array([3,4,5,6])})
A B F Level price
0 A d apple high 3
1 A d orange low 4
2 B b peach high 5
3 F f pear medium 6
df3=df1._append(df2,ignore_index=False)
print(df3)
A B v1 v2 F Level price
0 A a 1.0 low NaN NaN NaN
1 B a 1.0 medium NaN NaN NaN
2 B b 2.0 medium NaN NaN NaN
3 C c 3.0 high NaN NaN NaN
4 D c 3.0 low NaN NaN NaN
5 E e 1.0 high NaN NaN NaN
0 A d NaN NaN apple high 3.0
1 A d NaN NaN orange low 4.0
2 B b NaN NaN peach high 5.0
3 F f NaN NaN pear medium 6.0
可以看出,若有同名公共列,直接拼接最后列名会取并集,一个 dataframe 没有的列,在另一 dataframe 里其值为NaN
三、数据堆叠
有时进行数据处理后会得到一个只有数值的数组,可以用以下几种方法进行直接堆叠,实际过程中注意此种方法没有连接条件,建议使用已排好序的数据
这里以二维数据举例
(一)vstack()
import numpy as np
data1 = [[11, 12, 13], [14, 15, 16]]
data2 = [[41, 42, 43], [44, 45, 46]]
arr1 = np.array(data1)
arr1
arr2 = np.array(data2)
arr2
-----
array([[11, 12, 13],
[14, 15, 16]])
array([[41, 42, 43],
[44, 45, 46]])
进行合并,vstack是进行行的合并
a = np.vstack((arr1, arr2))
print(a)
[[11 12 13]
[14 15 16]
[41 42 43]
[44 45 46]]
(二)hstack()
b = np.hstack((arr1, arr2))
print(b)
-----
[[11 12 13 41 42 43]
[14 15 16 44 45 46]]
总结:在一维或二维甚至三维数组中,以上两种函数可视为直接在行/列上进行数据堆叠
待补充更新:melt、pivot、explode、pivot_table
更多推荐



所有评论(0)