>>> import numpy as np
>>> import pandas as pd
>>> df = pd.read_csv('data/table.csv')
>>> df.head()
School Class ID Gender Address Height Weight Math Physics
0 S_1 C_1 1101 M street_1 173 63 34.0 A+
1 S_1 C_1 1102 F street_2 192 73 32.5 B+
2 S_1 C_1 1103 M street_2 186 82 87.2 B+
3 S_1 C_1 1104 F street_2 167 81 80.4 B-
4 S_1 C_1 1105 F street_4 159 64 84.8 B+
一、append与assign
1. append方法
(a)利用序列添加行(必须指定name)
>>> df_append = df.loc[:3,['Gender','Height']].copy()
>>> df_append
Gender Height
0 M 173
1 F 192
2 M 186
3 F 167
>>> s = pd.Series({'Gender':'F','Height':188},name='new_row')
>>> df_append.append(s)
Gender Height
0 M 173
1 F 192
2 M 186
3 F 167
new_row F 188
(b)用DataFrame添加表
>>> df_temp = pd.DataFrame({'Gender':['F','M'],'Height':[188,176]},index=['new_1','new_2'])
>>> df_append.append(df_temp)
Gender Height
0 M 173
1 F 192
2 M 186
3 F 167
new_1 F 188
new_2 M 176
2. assign方法
该方法主要用于添加列,列名直接由参数指定:
>>> s = pd.Series(list('abcd'),index=range(4))
>>> df_append.assign(Letter=s)
Gender Height Letter
0 M 173 a
1 F 192 b
2 M 186 c
3 F 167 d
可以一次添加多个列:
>>> df_append.assign(col1=lambda x:x['Gender']*2, col2=s)
Gender Height col1 col2
0 M 173 MM a
1 F 192 FF b
2 M 186 MM c
3 F 167 FF d
二、combine与update
1. comine方法
comine
和update
都是用于表的填充函数,可以根据某种规则填充
(a)填充对象
可以看出combine
方法是按照表的顺序轮流进行逐列循环的,而且自动索引对齐,缺失值为NaN
,理解这一点很重要
>>> df_combine_1 = df.loc[:1,['Gender','Height']].copy()
>>> df_combine_2 = df.loc[10:11,['Gender','Height']].copy()
>>> df_combine_1.combine(df_combine_2,lambda x,y:print(x,y))
0 M
1 F
10 NaN
11 NaN
Name: Gender, dtype: object 0 NaN
1 NaN
10 M
11 F
Name: Gender, dtype: object
0 173.0
1 192.0
10 NaN
11 NaN
Name: Height, dtype: float64 0 NaN
1 NaN
10 161.0
11 175.0
Name: Height, dtype: float64
Gender Height
0 NaN NaN
1 NaN NaN
10 NaN NaN
11 NaN NaN
(b)一些例子
例①:根据列均值的大小填充
# 例子1
>>> df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
>>> df2 = pd.DataFrame({'A': [8, 7], 'B': [6, 5]})
>>> df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y)
A B
0 8 6
1 7 5
例②:索引对齐特性(默认状态下,后面的表没有的行列都会设置为NaN)
>>> df2 = pd.DataFrame({'B': [8, 7], 'C': [6, 5]},index=[1,2])
>>> df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y)
A B C
0 NaN NaN NaN
1 NaN 8.0 6.0
2 NaN 7.0 5.0
例③:使得df1原来符合条件的值不会被覆盖
>>> df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y,overwrite=False)
A B C
0 1.0 NaN NaN
1 2.0 8.0 6.0
2 NaN 7.0 5.0
例④:在新增匹配df2的元素位置填充-1
>>> df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y,fill_value=-1)
A B C
0 1.0 -1.0 -1.0
1 2.0 8.0 6.0
2 -1.0 7.0 5.0
(c)combine_first方法
这个方法作用是用df2
填补df1
的缺失值,功能比较简单,但很多时候会比combine
更常用,下面举两个例子:
>>> df1 = pd.DataFrame({'A': [None, 0], 'B': [None, 4]})
>>> df2 = pd.DataFrame({'A': [1, 1], 'B': [3, 3]})
>>> df1.combine_first(df2)
A B
0 1.0 3.0
1 0.0 4.0
>>> df1 = pd.DataFrame({'A': [None, 0], 'B': [4, None]})
>>> df2 = pd.DataFrame({'B': [3, 3], 'C': [1, 1]}, index=[1, 2])
>>> df1.combine_first(df2)
A B C
0 NaN 4.0 NaN
1 0.0 3.0 1.0
2 NaN 3.0 1.0
2. update方法
(a)三个特点
①返回的框索引只会与被调用框的一致(默认使用左连接,下一节会介绍)
②第二个框中的nan元素不会起作用
③没有返回值,直接在df上操作
(b)例子
例①:索引完全对齐情况下的操作
>>> df1 = pd.DataFrame({'A': [1, 2, 3],
'B': [400, 500, 600]})
>>> df2 = pd.DataFrame({'B': [4, 5, 6],
'C': [7, 8, 9]})
>>> df1.update(df2)
>>> df1
A B
0 1 4
1 2 5
2 3 6
例②:部分填充
>>> df1 = pd.DataFrame({'A': ['a', 'b', 'c'],
'B': ['x', 'y', 'z']})
>>> df2 = pd.DataFrame({'B': ['d', 'e']}, index=[1,2])
>>> df1.update(df2)
>>> df1
A B
0 a x
1 b d
2 c e
例③:缺失值不会填充
>>> df1 = pd.DataFrame({'A': [1, 2, 3],
'B': [400, 500, 600]})
>>> df2 = pd.DataFrame({'B': [4, np.nan, 6]})
>>> df1.update(df2)
>>> df1
A B
0 1 4.0
1 2 500.0
2 3 6.0
三、concat方法
concat
方法可以在两个维度上拼接,默认纵向凭借(axis=0
),拼接方式默认外连接
所谓外连接,就是取拼接方向的并集,而'inner'
时取拼接方向(若使用默认的纵向拼接,则为列的交集)的交集
下面举一些例子说明其参数:
>>> df1 = pd.DataFrame({'A': ['A0', 'A1'],
'B': ['B0', 'B1']},
index = [0,1])
>>> df2 = pd.DataFrame({'A': ['A2', 'A3'],
'B': ['B2', 'B3']},
index = [2,3])
>>> df3 = pd.DataFrame({'A': ['A1', 'A3'],
'D': ['D1', 'D3'],
'E': ['E1', 'E3']},
index = [1,3])
默认状态拼接:
>>> pd.concat([df1,df2])
A B
0 A0 B0
1 A1 B1
2 A2 B2
3 A3 B3
axis=1
时沿列方向拼接:
>>> pd.concat([df1,df2],axis=1)
A B A B
0 A0 B0 NaN NaN
1 A1 B1 NaN NaN
2 NaN NaN A2 B2
3 NaN NaN A3 B3
join
设置为内连接(由于axis=0
,因此列取交集):
>>> pd.concat([df3,df1],join='inner')
A
1 A1
3 A3
0 A0
1 A1
join
设置为外链接:
>>> pd.concat([df3,df1],join='outer',sort=True) #sort设置列排序,默认为False
A B D E
1 A1 NaN D1 E1
3 A3 NaN D3 E3
0 A0 B0 NaN NaN
1 A1 B1 NaN NaN
verify_integrity
检查列是否唯一:
>>> #pd.concat([df3,df1],verify_integrity=True,sort=True) 报错
同样,可以添加Series
:
>>> s = pd.Series(['X0', 'X1'], name='X')
>>> pd.concat([df1,s],axis=1)
A B X
0 A0 B0 X0
1 A1 B1 X1
key
参数用于对不同的数据框增加一个标号,便于索引:
>>> pd.concat([df1,df2], keys=['x', 'y'])
A B
x 0 A0 B0
1 A1 B1
y 2 A2 B2
3 A3 B3
>>> pd.concat([df1,df2], keys=['x', 'y']).index
MultiIndex([('x', 0),
('x', 1),
('y', 2),
('y', 3)],
)
四、merge与join
1. merge函数
merge
函数的作用是将两个pandas对象横向合并,遇到重复的索引项时会使用笛卡尔积,默认inner
连接,可选left
、outer
、right
连接
所谓左连接,就是指以第一个表索引为基准,右边的表中如果不再左边的则不加入,如果在左边的就以笛卡尔积的方式加入
merge/join
与concat
的不同之处在于on
参数,可以指定某一个对象为key
来进行连接
同样的,下面举一些例子:
>>> left = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
>>> right = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
>>> right2 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3']})
以key1
为准则连接,如果具有相同的列,则默认suffixes=('_x','_y')
:
>>> pd.merge(left, right, on='key1')
key1 key2_x A B key2_y C D
0 K0 K0 A0 B0 K0 C0 D0
1 K0 K1 A1 B1 K0 C0 D0
2 K1 K0 A2 B2 K0 C1 D1
3 K1 K0 A2 B2 K0 C2 D2
4 K2 K1 A3 B3 K0 C3 D3
以多组键连接:
>>> pd.merge(left, right, on=['key1','key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
默认使用inner
连接,因为merge
只能横向拼接,所以取行向上keys
的交集,下面看如果使用how=outer
参数
注意:这里的how
就是concat
的join
>>> pd.merge(left, right, how='outer', on=['key1','key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
5 K2 K0 NaN NaN C3 D3
左连接:
>>> pd.merge(left, right, how='left', on=['key1', 'key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K0 K1 A1 B1 NaN NaN
2 K1 K0 A2 B2 C1 D1
3 K1 K0 A2 B2 C2 D2
4 K2 K1 A3 B3 NaN NaN
右连接:
>>> pd.merge(left, right, how='right', on=['key1', 'key2'])
key1 key2 A B C D
0 K0 K0 A0 B0 C0 D0
1 K1 K0 A2 B2 C1 D1
2 K1 K0 A2 B2 C2 D2
3 K2 K0 NaN NaN C3 D3
如果还是对笛卡尔积不太了解,请务必理解下面这个例子,由于B的所有元素为2,因此需要6行:
>>> left = pd.DataFrame({'A': [1, 2], 'B': [2, 2]})
>>> right = pd.DataFrame({'A': [4, 5, 6], 'B': [2, 2, 2]})
>>> pd.merge(left, right, on='B', how='outer')
A_x B A_y
0 1 2 4
1 1 2 5
2 1 2 6
3 2 2 4
4 2 2 5
5 2 2 6
validate
检验的是到底哪一边出现了重复索引,如果是“one_to_one”
则两侧索引都是唯一,如果"one_to_many"
则左侧唯一
>>> left = pd.DataFrame({'A': [1, 2], 'B': [2, 2]})
>>> right = pd.DataFrame({'A': [4, 5, 6], 'B': [2, 3, 4]})
>>> #pd.merge(left, right, on='B', how='outer',validate='one_to_one') #报错
>>> left = pd.DataFrame({'A': [1, 2], 'B': [2, 1]})
>>> pd.merge(left, right, on='B', how='outer',validate='one_to_one')
A_x B A_y
0 1.0 2 4.0
1 2.0 1 NaN
2 NaN 3 5.0
3 NaN 4 6.0
indicator
参数指示了,合并后该行索引的来源
>>> df1 = pd.DataFrame({'col1': [0, 1], 'col_left': ['a', 'b']})
>>> df2 = pd.DataFrame({'col1': [1, 2, 2], 'col_right': [2, 2, 2]})
>>> pd.merge(df1, df2, on='col1', how='outer', indicator=True) #indicator='indicator_column'也是可以的
col1 col_left col_right _merge
0 0 a NaN left_only
1 1 b 2.0 both
2 2 NaN 2.0 right_only
3 2 NaN 2.0 right_only
2. join函数
join
函数作用是将多个pandas对象横向拼接,遇到重复的索引项时会使用笛卡尔积,默认左连接,可选inner
、outer
、right
连接
>>> left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=['K0', 'K1', 'K2'])
>>> right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
'D': ['D0', 'D2', 'D3']},
index=['K0', 'K2', 'K3'])
>>> left.join(right)
A B C D
K0 A0 B0 C0 D0
K1 A1 B1 NaN NaN
K2 A2 B2 C2 D2
对于many_to_one
模式下的合并,往往join
更为方便
同样可以指定key
:
>>> left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key': ['K0', 'K1', 'K0', 'K1']})
>>> right = pd.DataFrame({'C': ['C0', 'C1'],
'D': ['D0', 'D1']},
index=['K0', 'K1'])
>>> left.join(right, on='key')
A B key C D
0 A0 B0 K0 C0 D0
1 A1 B1 K1 C1 D1
2 A2 B2 K0 C0 D0
3 A3 B3 K1 C1 D1
多层key
:
>>> left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1']})
>>> index = pd.MultiIndex.from_tuples([('K0', 'K0'), ('K1', 'K0'),
('K2', 'K0'), ('K2', 'K1')],names=['key1','key2'])
>>> right = pd.DataFrame({'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']},
index=index)
>>> left.join(right, on=['key1','key2'])
A B key1 key2 C D
0 A0 B0 K0 K0 C0 D0
1 A1 B1 K0 K1 NaN NaN
2 A2 B2 K1 K0 C1 D1
3 A3 B3 K2 K1 C3 D3
相关文章
Python Pandas 第1章 基础
Python Pandas 第2章 索引
Python Pandas 第3章 分组
Python Pandas 第4章 变形
Python Pandas 第5章 合并
Python Pandas 第6章 缺少数据
Python Pandas 第7章 文本数据
Python Pandas 第8章 分类数据
Python Pandas 第9章 时序数据