源自pandas组队学习计划
复习提纲
一、append和assign
- append方法
- 利用序列添加行(须指定name)
- 用DataFrame添加表
(添加不会作用在原数据框中,需指定接收变量 )
- assign方法
- 用于添加列,列名在形式参数时指定
- 多列同时添加
二、combine和update
- combine方法
- combine和update方法用途:表的填充,设定填充规则
- (a)填充对象
combine函数是按照两个数据框对应的一列列进行数据操作的!!
理解:可以看出combine方法是按照表的顺序轮流进行逐列循环的,而且自动索引对齐,缺失值为NaN
这里给出的例子中输出数据全为NaN,这是因为后面的func指定的是打印,正常应该执行np.minimum等运算,按列取值计算后 输出
- (b)一些例子
例1中:列、行对应的元素进行比较,这里是对整列的mean做对比的。我尝试了一下整列直接比较是报错的,提示我需要加上x.any()或者x.all()之类的方法.
例2中:索引对齐特性,也就是在默认状态下,后面的表没有的行列会设置成NaN,可以理解成,两个数据框中同等位置的元素不全,就没法比较啦!
在帮助文档中,提示使用 fill_value=-5
这样的形参补足缺失数据
例3中:“使得df1原来符合条件的值不会被覆盖”,用overwrite=False
实现,大白话就是:有个别缺失数据没关系,df1有的数据,df2没有,那运算结果算df1的
这里有个想法:他们之间是咋对比的呢,如果df2中仅仅缺一个数据,不是缺两个,那怎么判别呢??
例4:新增匹配df2的元素位置填充-1
- (c)combine_first方法
作用:用df2填补df1的缺失值,简单实用,这意味着可以不加形式参数。
- update方法
- (a)了解3特点
第二个数据框中的nan元素不起作用。
没有返回值,直接在df对象上操作。
返回的数据框索引只会与被调用的框一致(默认左连接,这里不懂的话看个例子就好了。)
- (b)例子
pandas.DataFrame.update
体现的原则基本是:按照索引来对齐更新,没有的就不填充(部分填充),缺失值不会填充。
三、concat方法
concat方法可以在两个维度上拼接,默认纵向拼接(axis=0),拼接方式默认外连接。
简单:
>>> s1 = pd.Series(['a', 'b'])
>>> s2 = pd.Series(['c', 'd'])
>>> pd.concat([s1, s2])
0 a
1 b
0 c
1 d
dtype: object
外连接:取拼接方向的并集,join=‘outer’ ,
而join='inner’时取拼接方向(若使用默认的纵向拼接,则为列的交集)的交集。
-
axis=1 时设置沿着列方向拼接
-
形式参数join='inner’表示设置为内连接,例如默认axis=0,列取交集,即数据相交的那一个
-
可以将Series添加到df中
s = pd.Series(['x1','x3'], name='x')
pd.concat([df1, s], axis=1)
- key参数
四、merge和join
- merge函数
作用:将两个pandas对象横向合并,在遇到重复的索引项时使用笛卡尔积,默认how='inner’连接,可选left、outer、right连接。
左连接:以第一个表索引为基准,右边的表中的索引不在左边则不加入,如果在左边则以笛卡尔积的方式加入。
merge与join函数与concat的不同在于on参数,可指定某个对象为key来连接。
如 pd.merge(df1,df2,how='outer'
就是将两个数据并集,没有的数据为nan。这里的how就是concat方法中的join
理解笛卡尔积:[2, 2]与[2, 2, 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’ validate检验的是到底哪一边出现了重复索引,如果是“one_to_one”则两侧索引都是唯一,如果"one_to_many"则左侧唯一???
-
indicator=True 显示合并后该行索引的来源
- join函数
作用:将多个pandas对象横向拼接,遇到重复的索引项使用笛卡尔积。
默认左连接,也有inner、outer、right链接。
left.join(right, on='key')
默认也是指定索引链接。
练习一
# (a) 每个公司有多少员工满足如下条件:既出现第一张表,又出现在第二张表。
r = data1.merge(data2, how='inner', on=['Company','Name'])
display(r)
print('满足..条件的人数为:', r.shape[0])
# (b) 将所有不符合(a)中条件的行筛选出来,合并为一张新表,列名与原表一致。
L = list(r['Name'])
data1_b = data1[ ~data1['Name'].isin(L)]
data2_b = data2[ ~data2['Name'].isin(L)]
result_b = pd.concat([data1_b, data2_b], axis=0)
display(result_b.info())
result_b.head()
# (c) 现在需要编制所有80位员工的信息表,对于(b)中的员工要求不变,对于满足(a)条件员工,它们在某个指标的数值,取偏离它所属公司中满足(b)员工的均值数较小的哪一个,例如:P公司在两张表的交集为{p1},并集扣除交集为{p2,p3,p4},那么如果后者集合的工资均值为1万元,且p1在表1的工资为13000元,在表2的工资为9000元,那么应该最后取9000元作为p1的工资,最后对于没有信息的员工,利用缺失值填充。
在(a)题中,使用join报错了:
en(left_on) must equal the number of levels in the index of "right"
,借此能认识到merge与join方法的不同,最少join必需行数相同。
【练习二】
有2张课程的分数表(分数随机生成),但专业课(学科基础课、专业必修课、专业选修课)与其他课程混在一起,请解决如下问题:
# (a) 将两张表分别拆分为专业课与非专业课(结果为四张表)
t1_a1 = t1[ (t1['课程类别']=='专业必修课') | (t1['课程类别']=='学科基础课') | (t1['课程类别']=='专业选修课')]
print('专业课:')
display(t1_a1.head())
print('非专业课::')
t1_a2 = t1[ ~((t1['课程类别']=='专业必修课') | (t1['课程类别']=='学科基础课') | (t1['课程类别']=='专业选修课'))]
display(t1_a2)
# 此时看到另一种写法:
t2_a1 = t2.query("课程类别 in ['专业必修课','学科基础课','专业选修课']")
t2_a2 = t2.query("课程类别 not in ['专业必修课','学科基础课','专业选修课']")
print("表2的 专业课:")
display(t2_a1.head())
print("表2的 非专业课:")
display(t2_a2.head())
# (b) 将两张专业课的分数表和两张非专业课的分数表分别合并。
result_b1 = pd.concat([t1_a1, t2_a1], axis=0)
result_b2 = pd.concat([t1_a2, t2_a2], axis=0) #非专业课程 合并
display(result_b2.head())
# (c) 不使用(a)中的步骤,请直接读取两张表合并后拆分。 # 这个思路,数据操作量大些
cc = pd.concat([t1, t2],axis=0)
cc_2 = cc.query("课程类别 in ['专业必修课','学科基础课','专业选修课']") #专业课
cc_3 = cc.query("课程类别 not in ['专业必修课','学科基础课','专业选修课']") #
cc_3.head()
# (d) 专业课程中有缺失值吗,如果有的话请在完成(3)的同时,用组内(3种类型的专业课)均值填充缺失值后拆分。
display( cc_2[cc_2.isnull().values==True] )
cc_2['分数'] = cc_2.groupby('课程类别').transform(lambda x:x.fillna(x.mean()))['分数']
display(cc_2.isnull().all())
# 拆分:还是用上面的query拆分。
我对比了一下groupby前后的专业课表,确实是仅仅缺值数据被动了,其他没有出现错误。
这说明在分组、转换值之后,数据框依然保持着原来的顺序,不因被分组了而颠倒为分组顺序。