Task03:数据重构

数据重构

数据的合并

数据合并主要有 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 种:

  1. concat 为基于索引的的拼接,即可以纵向拼接,也可以横向拼接,可以一次拼接 2个及以上的对象
  2. merge 可以将两个对象横向拼接,连接键可以自由指定
  3. join 可以将两个对象横向拼接,左边的连接键可以自由指定,右边的连接键必须是索引
  4. append 可以将两个对象根据列索引纵向拼接,但该方法将在未来的版本被移除

分组操作的通用模式为:df.groupby(分组依据)[数据来源].具体操作,其中具体操作又可以分为 agg(聚合函数)、apply(自定义操作)、transform(数据转换)、filter(条件过滤)4 种。

idxmax() 方法可以用于获取最大值所在的索引,从而获取最大值所在的数据。

浙ICP备19012682号