数据重构
数据的合并
数据合并主要有 pd.concat()
、pd.merge()
、pd.join()
和 df.append()
等方法
concat
pd.concat()
是拼接两个 DataFrame 最常用的方法,其常用参数如下:
参数 | 说明 |
---|---|
objs | 待合并的对象列表 |
axis | 0 表示纵向拼接,1 表示横向拼接 |
join | 拼接方式,‘outer’ 表示外连接,‘inner’ 表示内连接 |
ignore_index | 是否重置索引,默认 False |
拼接泰塔尼克号的 4 个子数据集,可以分别将两个上半部分文件、两个下半部分文件横向拼接,得到上、下部分完整的文件,再进行一次纵向拼接,即可获取完整的数据:
>>> train_up = pd.concat([train_left_up, train_right_up], axis=1)
>>> train_down = pd.concat([train_left_down, train_right_down], axis=1)
>>> result = pd.concat([train_up, train_down], ignore_index=True)
>>> result.tail(3)
join
df.join(other, how='left')
是 DataFrame 上的一个方法,可以将两个 DataFrame 横向拼接。
用 join()
连接泰坦尼克数据集实现:
>>> join_up = train_left_up.join(train_right_up)
>>> join_down = train_left_down.join(train_right_down)
>>> result = join_up.append(join_down, ignore_index=True)
<stdin>:1: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
>>> result.tail(3)
merge
pd.merge()
也是将两个 DataFrame 横向拼接,相比 concat()
和 join()
,可以设置除索引以外的其他列标签进行拼接,更为灵活,其常用参数为:
参数 | 说明 |
---|---|
left、ringt | 待拼接的左右两个对象 |
how | 拼接方式,有 ‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’ 5 种 |
on | 指定用于连接的列标签,必须同时存在于两边 |
left_on | 指定左侧用于连接的列名 |
right_on | 作用于右边对象,功能同上 |
left_index | 布尔参数,如果为 True 使用左边的索引为连接键 |
right_index | 作用于右边对象,功能同上 |
用 merge()
连接泰坦尼克号数据集:
>>> merge_up = pd.merge(train_left_up, train_right_up, left_index=True, right_index=True)
>>> merge_down = pd.merge(train_left_down, train_right_down, left_index=True, right_index=True)
>>> result = merge_up.append(merge_down, ignore_index=True)
<stdin>:1: FutureWarning: The frame.append method is deprecated and will be removed from pandas in a future version. Use pandas.concat instead.
>>> result.tail(3)
拼接方法总结
方法 | 拼接数量 | 拼接方向 | 连接键 |
---|---|---|---|
concat | 2个或更多 | 横向或纵向 | 索引 |
append | 2个 | 纵向 | 列索引 |
merge | 2个 | 横向 | 两边均可自由指定 |
join | 2个 | 横向 | 左边可指定,右边必须为索引 |
其中 append()
方法将在后续版本中被移除,推荐使用 concat()
纵向拼接。
转变为 Series
stack()
函数可以将数据进行重构,把 DataFrame 的列索引转变为二级行索引:
>>> result.stack()
unstack()
是 stack()
的逆操作,将行索引转变为列索引:
>>> result.stack().unstack()
分组聚合
一次分组操作主要可以分解为 3 个部分:分组依据(即根据哪列或哪几列数据进行分组)、数据来源(即分组后需要进行操作的数据有哪些)和具体操作(即要对分组后的数据执行的操作),分组操作可以总结为一下模式:
df.groupby(分组依据)[数据来源].具体操作
具体操作又可分为 agg(聚合函数)、apply(自定义操作)、transform(数据转换)、filter(条件过滤)4 种
agg 聚合
如果不使用 agg()
方法聚合,要统计男女的平均票价和存活人数就需要执行两次分组,然后再进行数据拼接:
>>> sex_fare = df.groupby('Sex')['Fare'].mean()
>>> sex_survived = df.groupby('Sex')['Survived'].sum()
>>> # 此处使用 concat 方法最为方便
>>> sex_fare_survived = pd.concat([sex_fare, sex_survived], axis=1)
>>> sex_fare_survived
Fare Survived
Sex
female 44.479818 233
male 25.523893 109
使用 agg()
方法聚合可以将上述过程一步到位,大大简化操作:
>>> sex_fare_survived = df.groupby('Sex').agg({'Fare': 'mean', 'Survived': 'sum'}).rename(columns={'Fare': 'Fare_mean', 'Survived': 'Survived_sum'})
>>> sex_fare_survived
Fare_mean Survived_sum
Sex
female 44.479818 233
male 25.523893 109
根据多字段分组
分组的依据可以是多个字段,只需要传入一个列标签构成的列表,本题中分别是船舱等级和年龄两个字段:
df.groupby(['Pclass', 'Age'])['Fare'].mean()
获取最大值所在的数据
先使用分组获取每个年龄的存活人数:
>>> age_survived = df.groupby('Age')['Survived'].sum()
找出存活人数最多所在的索引可以使用 idxmax()
方法,然后再进行索引就可以获取存活人数最多的数据:
>>> age_survived[[age_survived.idxmax()]]
Age
24.0 15
存活人数最多的年龄为 24 岁,存活 15 人。
计算存活率:
>>> # 获取存活总人数
>>> tot_num = df['Survived'].sum()
>>>
>>> # 计算最高存活率
>>> survived_ratio = age_survived.max() / tot_num
总结
数据拼接主要有 pd.concat()
、pd.merge()
、df.join()
、df.append()
4 种:
- concat 为基于索引的的拼接,即可以纵向拼接,也可以横向拼接,可以一次拼接 2个及以上的对象
- merge 可以将两个对象横向拼接,连接键可以自由指定
- join 可以将两个对象横向拼接,左边的连接键可以自由指定,右边的连接键必须是索引
- append 可以将两个对象根据列索引纵向拼接,但该方法将在未来的版本被移除
分组操作的通用模式为:df.groupby(分组依据)[数据来源].具体操作
,其中具体操作又可以分为 agg(聚合函数)、apply(自定义操作)、transform(数据转换)、filter(条件过滤)4 种。
idxmax()
方法可以用于获取最大值所在的索引,从而获取最大值所在的数据。