数据规整:数据库风格的 dataframe 连接(merge方法),根据索引合并(join方法)

2 联合与合并数据集

包含在pandas 对象的数据可以通过多种方式联合在一起:

  • pandas.merge 根据一个或多个键将行进行链接。
  • pandas.concat 使对象在轴向上进行粘合或堆叠
  • combine_first 实例方法允许将重叠的数据拼接在一起,以使用一个对象中的值填充另一个对象中的缺失值

2.1 数据库风格的 dataframe 连接

df1=pd.DataFrame({'key':['b','b','a','c','a','a','b'],'data1':range(7)})
df2=pd.DataFrame({'key':['a','b','d'],'data2':range(3)})
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
  key	data2
0	a	0
1	b	1
2	d	2

pd.merge(df1,df2)            # 多对一链接的例子,df1 的 key 列有多个a b ,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

pd.merge(df1,df2,on='key')            # 这是显示的指定链接的键


df3=pd.DataFrame({'lkey':['b','b','a','c','a','a','b'],'data1':range(7)})
df4=pd.DataFrame({'rkey':['a','b','d'],'data2':range(3)})
pd.merge(df3,df4,left_on='lkey',right_on='rkey')        # 如果每个对象的列名是不同的,你可以分别为他们指定列名
	lkey	data1	rkey	data2
0	b	0	b	1
1	b	1	b	1
2	b	6	b	1
3	a	2	a	0
4	a	4	a	0
5	a	5	a	0

可以看到,结果中缺少了 ‘c’ 和 ‘d’ 的值以及相关数据。默认情况下,merge 做的是内连接(inner join),结果中的键是两张表的交集。其他可选的选项有 left right outer。外连接( outer join)是键的并集,

pd.merge(df1,df2,how='outer')
	key	data1	data2
0	b	0.0	1.0
1	b	1.0	1.0
2	b	6.0	1.0
3	a	2.0	0.0
4	a	4.0	0.0
5	a	5.0	0.0
6	c	3.0	NaN
7	d	NaN	2.0
how参数不同连接类型 行为
inner 只对两张表都有的键的交集进行联合。
left 对所有左表的键进行联合
right 对所有右表的键进行联合
outer 对两张表都有的键的并集进行联合。

多对多的合并:

df1=pd.DataFrame({'key':['b','b','a','c','a','b'],'data1':range(6)})
df2=pd.DataFrame({'key':['a','b','a','b','d'],'data2':range(5)})
df1
  key	data1
0	b	0
1	b	1
2	a	2
3	c	3
4	a	4
5	b	5
df2
	key	data2
0	a	0
1	b	1
2	a	2
3	b	3
4	d	4

pd.merge(df1,df2,on='key',how='left')
	key	data1	data2
0	b	0	1.0
1	b	0	3.0
2	b	1	1.0
3	b	1	3.0
4	a	2	0.0
5	a	2	2.0
6	c	3	NaN
7	a	4	0.0
8	a	4	2.0
9	b	5	1.0
10	b	5	3.0

多对多连接是行的笛卡尔积,就是A={a,b}, B={0,1,2},则A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}

上面这个以df1 为准来连接,df1 中 b=[0,1,5] a=[2,4] c=3 ,df2 中 b=[1,3] a=[0,2] 。按笛卡尔积来算的话,连接后的 b 应该有6个,[(0,1),(0,3),(1,1),(1,3),(5,1),(5,3)] 对照上面确实是,按照 df1 的索引排列。连接方法仅影响结果中显示的不同键值

pd.merge(df1,df2,how='inner')

  key	data1	data2
0	b	0	1
1	b	0	3
2	b	1	1
3	b	1	3                  # 两个键的交集。
4	b	5	1
5	b	5	3
6	a	2	0
7	a	2	2
8	a	4	0
9	a	4	2


left = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
                     'key2': ['one', 'two', 'one'],
                     'lval': [1, 2, 3]})
right = pd.DataFrame({'key1': ['foo', 'foo', 'bar', 'bar'],
                      'key2': ['one', 'one', 'one', 'two'],
                      'rval': [4, 5, 6, 7]})
pd.merge(left, right, on=['key1', 'key2'], how='outer')
	key1	key2	lval	rval
0	foo	one	1.0	4.0                        # 使用多个键进行合并,传入一个列名的列表。
1	foo	one	1.0	5.0
2	foo	two	2.0	NaN
3	bar	one	3.0	6.0
4	bar	two	NaN	7.0

# 合并操作最后的问题是如何处理重叠的列名,虽然可以通过 rname 的方式重命名轴标签,
# 但是 merge 的suffixes 后缀选项用于在左右两边dataframe 对象的重叠列名后指定需要添加的字符串
pd.merge(left,right,on='key1')
	key1	key2_x	lval	key2_y	rval
0	foo	one	1	one	4
1	foo	one	1	one	5
2	foo	two	2	one	4
3	foo	two	2	one	5
4	bar	one	3	one	6
5	bar	one	3	two	7

pd.merge(left,right,on='key1',suffixes=('_left','_right'))
key1	key2_left	lval	key2_right	rval
0	foo	one	1	one	4
1	foo	one	1	one	5
2	foo	two	2	one	4
3	foo	two	2	one	5
4	bar	one	3	one	6
5	bar	one	3	two	7

在这里插入图片描述
在这里插入图片描述

2.2 根据索引合并

某些情况下,dataframe 中用于合并的键是他的索引。在这种情况下,可以传递 left_index=True or right_index=True 来表示索引需要用来作为合并的键。

left1 = pd.DataFrame({'key': ['a', 'b', 'a', 'a', 'b', 'c'],
                      'value': range(6)})
right1 = pd.DataFrame({'group_val': [3.5, 7]}, index=['a', 'b'])
left1
	key	value
0	a	0
1	b	1
2	a	2
3	a	3
4	b	4
5	c	5
right1
group_val
a	3.5
b	7.0

pd.merge(left1, right1, left_on='key', right_index=True)        # 就是将右边的索引当键了
	key	value	group_val
0	a	0	3.5
2	a	2	3.5
3	a	3	3.5
1	b	1	7.0
4	b	4	7.0

lefth = pd.DataFrame({'key1': ['Ohio', 'Ohio', 'Ohio',
                               'Nevada', 'Nevada'],
                      'key2': [2000, 2001, 2002, 2001, 2002],
                      'data': np.arange(5.)})
righth = pd.DataFrame(np.arange(12).reshape((6, 2)),
                      index=[['Nevada', 'Nevada', 'Ohio', 'Ohio',
                              'Ohio', 'Ohio'],
                             [2001, 2000, 2000, 2000, 2001, 2002]],
                      columns=['event1', 'event2'])
lefth
    key1	key2	data
0	Ohio	2000	0.0
1	Ohio	2001	1.0
2	Ohio	2002	2.0
3	Nevada	2001	3.0
4	Nevada	2002	4.0
righth
		event1	event2
Nevada	2001	0	1
        2000	2	3
Ohio	2000	4	5
        2000	6	7
        2001	8	9
        2002	10	11
        
pd.merge(lefth,righth,left_on=['key1','key2'],right_index=True)   # 在多层索引的情况下,索引上连接是一个隐式的多键合并
    key1	key2	data event1	event2            # 这种情况下,必须以列表的方式指名合并所需多个列
0	Ohio	2000	0.0	4	5               
0	Ohio	2000	0.0	6	7
1	Ohio	2001	1.0	8	9             
2	Ohio	2002	2.0	10	11                    # 耐心看看还是能看懂的,
3	Nevada	2001	3.0	0	1

left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],
                     index=['a', 'c', 'e'],
                     columns=['Ohio', 'Nevada'])
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],
                      index=['b', 'c', 'd', 'e'],
                      columns=['Missouri', 'Alabama'])
left2
    Ohio	Nevada
a	1.0	2.0
c	3.0	4.0
e	5.0	6.0
right2
 Missouri	Alabama
b	7.0	8.0
c	9.0	10.0
d	11.0	12.0
e	13.0	14.0
                       
pd.merge(left2, right2, how='outer', left_index=True, right_index=True)      # 使用两边的索引
   Ohio	Nevada	Missouri	Alabama
a	1.0	2.0	NaN	NaN
b	NaN	NaN	7.0	8.0
c	3.0	4.0	9.0	10.0
d	NaN	NaN	11.0	12.0
e	5.0	6.0	13.0	14.0                

dataframe 有一个方便的 join 方法, 用于按照索引合并,该方法也可以用于合并多个索引相同后相似但没有重叠列的 dataframe 对象。

left2.join(right2, how='outer')      # 上面那个我们也可以这么写。
	Ohio	Nevada	Missouri	Alabama
a	1.0	2.0	NaN	NaN
b	NaN	NaN	7.0	8.0
c	3.0	4.0	9.0	10.0
d	NaN	NaN	11.0	12.0
e	5.0	6.0	13.0	14.0

left1.join(right1, on='key')          # join 方法进行连接键上的左连接,完全保留左边 dataframe 的行索引。
	key	value	group_val
0	a	0	3.5
1	b	1	7.0
2	a	2	3.5
3	a	3	3.5
4	b	4	7.0
5	c	5	NaN

another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],
                       index=['a', 'c', 'e', 'f'],
                       columns=['New York', 'Oregon'])
another
  New York	Oregon
a	7.0	8.0
c	9.0	10.0
e	11.0	12.0
f	16.0	17.0     # 对于一些简单索引-索引合并,可以向join 方法传入一个dataframe 列表,这个方法可以替代更为通用的concat 函数

left2.join([right2,another],how='outer')
Ohio	Nevada	Missouri	Alabama	New York	Oregon        # 就是多加一些合并的数据吧。。。
a	1.0	2.0	NaN	NaN	7.0	8.0
c	3.0	4.0	9.0	10.0	9.0	10.0
e	5.0	6.0	13.0	14.0	11.0	12.0
b	NaN	NaN	7.0	8.0	NaN	NaN
d	NaN	NaN	11.0	12.0	NaN	NaN
f	NaN	NaN	NaN	NaN	16.0	17.0

好难啊,感觉整个人都傻了。。。。。。

猜你喜欢

转载自blog.csdn.net/weixin_46192930/article/details/106735238