动手学数据分析(3)——数据重构
本文为Datawhale8月组队学习——动手学数据分析课程的系列学习笔记。
数据来源
Kaggle小白入门首选练手项目——Kaggle-泰坦尼克号存活率
Ch2-2 数据重构
数据重构部分主要介绍了数据的合并、变形与分组。
数据合并与拼接
数据的合并与拼接一般涉及四个方法/函数:
函数/方法 | 使用场景 |
---|---|
concat() | 可以在两个维度上拼接(外连接) |
append() | DataFrame/Series的纵向拼接 |
merge() | 两个DataFrame的横向拼接(基于任意共有列) |
join() | 两个DataFrame的横向拼接(基于索引) |
其中,concat和append方法倾向于简单的连接,merge和join则类似数据库中的连接。
连接方式
这里回顾一下数据库的几种连接方式:
连接方式 | 含义 |
---|---|
内连接 | 两个表的交集,左表和右表都有的才显示出来 |
外连接(全连接) | 两个表的并集,有的都显示,连接后没有的值默认为空值 |
左连接(左外连接) | 以左表为基准,左表有的右表也有就显示,左表有的右表没有填空值 |
右连接(右外连接) | 以右表为基准,右表有的左表也有就显示,右表有的左表没有填空值 |
交叉连接(笛卡尔积) | 左表每行依此连接右表各行,左表有m行,右表有n行,则连接后有m×n行 |
concat
pd.concat
以列表(List)形式传入需要连接的DataFrame,并可以设置连接的方向(axis
),支持DataFrame/Series的组合,拼接方法默认为外连接(并集)。
1 | # keys参数可以方便辨别索引相同的行来源 |
append
即纵向拼接,补充部分样本。支持列数不同的表拼接,没有数据将默认为NaN。ignore_index
参数可以用于重置拼接后的数字索引。
merge/join
一般用于表的横向连接,二者都支持上面提到的几种连接方式how='left'/'right'/'outer'/'inner'
。主要差异在于join是靠索引进行连接的,而merge可以使用on
指定连接的键(基准列)。
merge也使用index作为键进行连接的方式:将left_index
与right_index
均置为True。
此外,二者默认的连接方式不同,merge默认为内连接,join默认为左连接。当二者遇到基准列重复项时会使用笛卡尔积(交叉连接)。
merge函数有两种,一种是DataFrame的方法,一种是pandas自带的函数,二者的效果是一致的。
尽管join也有on参数,但只是更改了传入表中要连接的准则列。
关于几个问题的思考
问题1:任务四和五中需要用到表的纵向连接,为什么都要求使用DataFrame的append方法,如果只要求使用merge或者join可不可以完成任务四和任务五呢?
思考:merge和join很少用于表的纵向连接,一般认为它无法用于纵向连接,但经过探索,在实际操作中,可以借助外连接实现表的纵向连接,只需传入的on
参数为所有列,即基准列为所有列。
1 | # 尝试1 |
这样的操作是有限制的,倘若出现重复的行,就会出现只保留一行的情况,并不建议使用。
问题2:如何实现交叉连接?(来自Datawhale成员的提问)
思路:用到此前提到的遇到基准列重复项时会使用笛卡尔积(交叉连接)的兴致,为两个表构造一个数值相同的列作为key。
1 | df1['key']=1 |
数据变形
主要用到stack()
和unstack()
方法。
- stack:最基础的变形函数,把Dataframe堆叠为二级索引的Series,可以看作将横向的索引放到纵向,参数
level
可指定变化的列索引是哪一层(或哪几层,需要列表) - unstack:stack的逆函数,可以把Series解回为DataFrame
二者都具有将表转置(横索引 ↔ 纵索引)的作用,更高级的方法参见
pivot()
数据分组
GroupBy运行机制
pandas中的数据分组基于GroupBy,既可用于Series也可用于DataFrame,groupby()
方法返回一个对应的没有经过计算的DataFrameGroupBy对象或SeriesGroupBy对象,该对象本身不会返回任何东西,只有当相应的方法被调用才会起作用。
基本使用方式:在通过groupby()
方法得到GroupBy对象后,可以使用其自带的各种统计量计算方法,将返回各组(列)的相应统计量(DataFrame/Series形式)
其运行机制如下:
即:根据输入的分组依据,运行groupby进行分组,后续使用统计函数时,同时对各个组应用该统计函数,并返回相应的统计量再聚合到一起以DataFrame形式返回。
对分组对象使用head函数,返回的是每个组的前几行,而不是数据集前几行。
groupby支持依据多列进行分组,分组后使用统计函数时会出现多级索引,可以使用多次
[]
操作器进行提取
基于列的聚合操作——agg
agg()
提供基于列的聚合操作。而groupby()
可以看做是基于行,或者说index的聚合操作。
- 可以传入列表
- 可以直接输入完整的函数名:[np.sum, np.count]
- 可以只输入统计函数名(字符串):[‘mean’, ‘sum’]
- 可以传入dict——{列1:统计函数1,列2:统计函数2}
- dict的values还可以为多个统计函数的列表
- 结合rename使用,方便识别统计量进行后续分析
1 | # 第一次尝试,可以使用numpy的函数 |
图片来源
Datawhale 动手学数据分析答疑群