import numpy as np
import pandas as pd
df= pd. read_csv( 'E:\jupyter Notebook\天池比赛\pandas学习\joyful-pandas-master\data\\table.csv' )
df. head( )
Unnamed: 0 School Class ID Gender Address Height Weight Math Physics 0 0 S_1 C_1 1101 M street_1 173 63 34.0 A+ 1 1 S_1 C_1 1102 F street_2 192 73 32.5 B+ 2 2 S_1 C_1 1103 M street_2 186 82 87.2 B+ 3 3 S_1 C_1 1104 F street_2 167 81 80.4 B- 4 4 S_1 C_1 1105 F street_4 159 64 84.8 B+
append and assign
append
利用序列添加行(必须指定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
利用DataFrame添加表
df_tmp= pd. DataFrame( { 'Gender' : [ 'F' , 'M' ] , 'Height' : [ 188 , 176 ] } , index= [ 'new_1' , 'new_2' ] )
df_append. append( df_tmp)
Gender Height 0 M 173 1 F 192 2 M 186 3 F 167 new_1 F 188 new_2 M 176
assign方法
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 and update
combine
combine 和 update都用于表填充函数,可以根据某种规则填充
1. 填充对象
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
df_combine_1
df_combine_2
相关例子
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)
2.索引对齐特性(默认状态下,后面的表没有行列都会设置为NaN)
df2= pd. DataFrame( { 'B' : [ 8 , 7 ] , 'C' : [ 6 , 5 ] } , index= [ 1 , 2 ] )
df2
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
3. 使得df1符合条件的值都不会被覆盖
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, overwrite= False )
A B C 0 1.0 NaN NaN 1 2.0 8.0 6.0 2 NaN 7.0 5.0
4.在新增匹配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
combine_first
df1= pd. DataFrame( { 'A' : [ None , 0 ] , 'B' : [ 4 , None ] } )
df2= pd. DataFrame( { 'A' : [ 3 , 3 ] , 'B' : [ 1 , 1 ] } )
df1. combine_first( df2)
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
update方法
update方法的特点
1.返回的框索引只会与被调用框的一致(默认使用左连接) 2.第二个框的NaN元素不会起作用 3.没有返回值,直接在df上操作
相关例子
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
df1= pd. DataFrame( { 'A' : [ 'a' , 'b' , 'c' ] , 'B' : [ 'x' , 'y' , 'z' ] } )
df2= pd. DataFrame( { 'B' : [ 'd' , 'e' ] } , index= [ 1 , 2 ] )
df1. update( df2)
df1
df1= pd. DataFrame( { 'A' : [ 1 , 2 , 3 ] , 'B' : [ 400 , 500 , 600 ] } )
df2= pd. DataFrame( { 'B' : [ 4 , np. nan, 6 ] } )
df1. update( df2)
df1
concat方法
contact方法可以在两个维度上拼接,默认纵向凭借(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] )
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设置为外连接
pd. concat( [ df1, df3] , join= 'outer' , sort= True )
A B D E 0 A0 B0 NaN NaN 1 A1 B1 NaN NaN 1 A1 NaN D1 E1 3 A3 NaN D3 E3
key参数用于对不同的数据框增加一个标号,便于索引
pd. concat( [ df1, df2] , keys= [ 'x' , 'y' ] )
pd. concat( [ df1, df2] , keys= [ 'x' , 'y' ] ) . index
MultiIndex([('x', 0),
('x', 1),
('y', 2),
('y', 3)],
)
merge and join
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
因为这里是用key1为对照的,那么按照笛卡尔积的规则,先看left的k0,然后找到right的k0所以k0合并之后有两行(2* 1),然后看left的k1,然后找到right的k1合并之后有两行(1* 2),最后看left里面的最后一个元素k2,找到right里面只有一个k2,所以k2最终有一行(1* 1)。这里的inner是指left的key1元素和right的key1元素取交集,而不是简单的行取交集。
df99= pd. merge( left, right, on= [ 'key1' , 'key2' ] )
df99
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的交集
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
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
问题与练习
问题
请思考什么是append/assign/combine/update/concat/merge/join各自最适合使用的场景,并举出相应的例子。
append:添加行 assign:添加列 combine:从两个表中根据某种规则,生成新的表(逐列相比较) updae:用表B填充表A concat:使用连接的方法从两个表中生成新的表(以集合的形式) merge:使用连接的方法从两个表中生成新的表(以key的形式) join:将多个pandas对象横向拼接,遇到重复的索引项时会使用笛卡尔积(可以使用左右连接)
merge_ordered和merge_asof的作用是什么?和merge是什么关系?
pd.merge_ordered #Perform merge with optional filling/interpolation. #Designed for ordered data like time series data. Optionally #另外 参数也更丰富,与merge相比 更有序?
请构造一个多级索引与多级索引合并的例子,尝试使用不同的合并函数。
index1 = pd. MultiIndex. from_tuples( [ ( 'K0' , 'K0' ) , ( 'K1' , 'K0' ) ,
( 'K2' , 'K0' ) , ( 'K2' , 'K1' ) ] , names= [ 'key1' , 'key2' ] )
index2 = pd. MultiIndex. from_tuples( [ ( 'K0' , 'K1' ) , ( 'K1' , 'K0' ) ,
( 'K2' , 'K0' ) , ( 'K3' , 'K1' ) ] , names= [ 'key1' , 'key2' ] )
left = pd. DataFrame( { 'A' : [ 'A0' , 'A1' , 'A2' , 'A3' ] ,
'B' : [ 'B0' , 'B1' , 'B2' , 'B3' ] ,
'C' : [ 'C0' , 'C1' , np. nan, 'C3' ] } , index= index1)
right = pd. DataFrame( { 'C' : [ 'C0' , 'C1' , 'C2' , 'C3' ] ,
'D' : [ 'D0' , 'D1' , 'D2' , 'D3' ] } ,
index= index2)
left. append( right)
A B C D key1 key2 K0 K0 A0 B0 C0 NaN K1 K0 A1 B1 C1 NaN K2 K0 A2 B2 NaN NaN K1 A3 B3 C3 NaN K0 K1 NaN NaN C0 D0 K1 K0 NaN NaN C1 D1 K2 K0 NaN NaN C2 D2 K3 K1 NaN NaN C3 D3
上文提到了连接的笛卡尔积,那么当连接方式变化时(inner/outer/left/right),这种笛卡尔积规则会相应变化吗?请构造相应例子。
inner:保留两对象都拥有的笛卡尔积 outer:保留全部的笛卡尔积 left:保留left对象所拥有的全部的笛卡尔积(默认缺失值用nan填充) rifht:保留right对象所拥有的全部的笛卡尔积(默认缺失值用nan填充)
练习
df_1= pd. read_csv( 'E:\jupyter Notebook\天池比赛\pandas学习\joyful-pandas-master\data\\Employee1.csv' )
df_2= pd. read_csv( 'E:\jupyter Notebook\天池比赛\pandas学习\joyful-pandas-master\data\\Employee2.csv' )
df_1. head( )
Company Name Age Height Weight Salary 0 A a1 47 188 63.7 25819 1 A a3 39 172 55.9 21983 2 A a4 43 158 62.5 21755 3 A a6 42 182 76.9 17354 4 A a7 49 171 94.6 6177
df_2. head( )
Company Name Age Height Weight Salary 0 A a1 30 156 91.2 28133 1 A a2 50 190 83.4 6673 2 A a3 34 168 96.6 16503 3 A a5 51 176 97.2 23294 4 A a6 37 183 93.2 19256
1. 每个公司有多少员工满足如下条件:既出现第一张表,又出现在第二张表。
df_12= df_1. iloc[ : , : 2 ] . assign( df_2. iloc[ : , : 1 ] )
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-115-5c4ba62fe72d> in <module>
----> 1 df_12=df_1.iloc[:,:2].assign(df_2.iloc[:,:1])
TypeError: assign() takes 1 positional argument but 2 were given