一、append与assign
append多用于将一行数据添加进行已有数据的一行中,
而assign则可以将多行数据同时添加。
df_append = df.loc[:3,['Gender', 'Height']].copy() #数字代表复制到第几行,而中括号中的内容表示复制哪个序列
print(df_append)
s = pd.Series({'Gender':'F','Height':188},name='new_row') #创建一个新的行。
print(df_append.append(s))
'''
Gender Height
0 M 173
1 F 192
2 M 186
3 F 167
new_row F 188
'''
df_temp = pd.DataFrame({'Gender':['F','M'],'Height':[188,176]},index=['new_1','new_2']) #同时创建多个行
print(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
'''
二、combine与update
combine函数可以用于合并两组数据并显示两组数据中符合要求的值。
而update函数则可以将新数据升级进旧数据中。
df1 = pd.DataFrame({'A':[1, 20], 'B':[3, 4]})
df2 = pd.DataFrame({'A':[8, 7], 'B':[6, 5]})
print(df1.combine(df2,lambda x,y : x if x.mean()>y.mean() else y)) #求平均值,大的输出
'''
A B
0 1 6
1 20 5
'''
df2 = pd.DataFrame({'B':[8, 7], 'C':[6, 5]}, index=[1,2])
print(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
'''
为什么这的值突然就有小数了呢?
print(df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y,overwrite=False)) #overwrite默认值为True
print(df1.combine(df2,lambda x,y:x if x.mean()>y.mean() else y,fill_value=-1))
'''
A B C
0 1.0 NaN NaN
1 20.0 8.0 6.0
2 NaN 7.0 5.0
A B C
0 1.0 -1.0 -1.0
1 20.0 8.0 6.0
2 -1.0 7.0 5.0
'''
从这个例子中可以得出,overwrite=False
可以将所有值显示出来,即不符合条件的值不会被覆盖
而fill_value=-1
则可以帮我们将缺失值填充。
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)
print(df1)
df1 = pd.DataFrame({'A': [1, 2, 3],
'B': [400, 500, 600]})
df2 = pd.DataFrame({'B': [4, np.nan, 6]})
df1.update(df2)
print(df1)
'''
A B
0 1 4
1 2 5
2 3 6
A B
0 1 4.0
1 2 500.0
2 3 6.0
'''
注意这里设置缺失值是用’np.nan’, 同时,缺失值是不会覆盖前值的。♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥♥
三、concat方法
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])
print(pd.concat([df1, df2], axis=1))
print(pd.concat([df1,df3],join='inner')) # 交集
print(pd.concat([df3,df1],join='outer',sort=True)) #'outer'表示并集,sort设置列排序
'''
A B A B
0 A0 B0 NaN NaN
1 A1 B1 NaN NaN
2 NaN NaN A2 B2
3 NaN NaN A3 B3
A
0 A0
1 A1
1 A1
3 A3
A B D E
1 A1 NaN D1 E1
3 A3 NaN D3 E3
0 A0 B0 NaN NaN
1 A1 B1 NaN NaN
'''
s = pd.Series(['X0', 'X1'], name='X')
print(pd.concat([df1,s],axis=1))
print(pd.concat([df1,df2], keys=['x', 'y']))
print(pd.concat([df1,df2], keys=['x', 'y']).index) # .index 的作用是表示出索引值的对应项
'''
A B X
0 A0 B0 X0
1 A1 B1 X1
A B
x 0 A0 B0
1 A1 B1
y 2 A2 B2
3 A3 B3
MultiIndex([('x', 0),
('x', 1),
('y', 2),
('y', 3)],
)
'''
四、merge与join
- 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']})
print(pd.merge(left, right, on='key1')) #以key1为索引,从right中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
'''
看清楚,这是从left中地key1中得到门牌号(索引值),拿着这个门牌号到right中找到对应的门牌号,随后开门,进屋,将屋内的物品一一列出来,如果找不到对应的门牌号,则拿不了里面的物品(其他值)。
问题与习题
1. 问题
【问题一】 请思考什么是append/assign/combine/update/concat/merge/join各自最适合使用的场景,并举出相应的例子。
append:增加行,必须要指定列名和索引名
assign:增加列,列名由参数决定
combine:两个表进行填充时
update:用df2中的值替换df中的值,最后结果直接在df1中更改,形状不变
concat:两个表进行连接,concat方法可以在两个维度上拼接,默认纵向凭借(axis=0),拼接方式默认外连接
所谓外连接,就是取拼接方向的并集,而’inner’时取拼接方向(若使用默认的纵向拼接,则为列的交集)的交集
merge:merge函数的作用是将两个pandas对象横向合并,遇到重复的索引项时会使用笛卡尔积,默认inner连接,可选left、outer、right连接
所谓左连接,就是指以第一个表索引为基准,右边的表中如果不再左边的则不加入,如果在左边的就以笛卡尔积的方式加入
join:join函数作用是将多个pandas对象横向拼接,遇到重复的索引项时会使用笛卡尔积,默认左连接,可选inner、outer、right连接
【问题二】 merge_ordered和merge_asof的作用是什么?和merge是什么关系?
merge_ordered函数允许组合时间序列和其他有序数据。 特别是它有一个可选的fill_method关键字来填充/插入缺失的数据。
merge_asof除了我们匹配最近的键而不是相等的键之外,其他的都类似于有序的left-join 。 对于左侧DataFrame中的每一行,我们选择右侧DataFrame中on键对应的值小于left的键对应的值的最后一行。 两个DataFrame必须按键排序。
【问题三】 请构造一个多级索引与多级索引合并的例子,尝试使用不同的合并函数。
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 1 6
1 20 5
'''
【问题四】 上文提到了连接的笛卡尔积,那么当连接方式变化时(inner/outer/left/right),这种笛卡尔积规则会相应变化吗?请构造相应例子。
会变化。
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']})
print(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
'''
print(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
'''
2.习题
【练习一】有2张公司的员工信息表,每个公司共有16名员工,共有五个公司,请解决如下问题:
df1 = pd.read_csv('Employee1.csv')
df2 = pd.read_csv('Employee2.csv')
(a) 每个公司有多少员工满足如下条件:既出现第一张表,又出现在第二张表。
n = set(df1['Name'].values.tolist())&set(df2['Name'].values.tolist())
print(n)
'''
{'d5', 'a3', 'e10', 'b1', 'c13', 'e8', 'a6', 'a1', 'b15', 'd10', 'e11', 'b7', 'c12', 'c3', 'b3', 'c10'}
'''
(b) 将所有不符合(a)中条件的行筛选出来,合并为一张新表,列名与原表一致。
df3 = pd.concat([df1,df2])
b = df3[~df3['Name'].isin(n)]
print(b.head())
'''
Company Name Age Height Weight Salary
2 A a4 43 158 62.5 21755
4 A a7 49 171 94.6 6177
5 A a8 51 168 89.5 3246
6 A a9 36 186 62.8 3569
7 A a13 58 190 75.9 21854
'''
。