如何重塑表格布局
来源:Pandas官网:https://pandas.pydata.org/docs/getting_started/intro_tutorials/index.html
笔记托管:https://gitee.com/DingJiaxiong/machine-learning-study
文章目录
- 如何重塑表格布局
- 导包
- 数据准备
- 【1】对表行进行排序
- 【2】长到宽表格式
- 【3】数据透视表
- 【4】宽幅到长幅
- 【小结】
导包
import pandas as pd
数据准备
使用存储为 CSV 的泰坦尼克号数据集。数据由以下数据列组成:
- 【PassengerId】乘客 ID:每位乘客的 ID。
- 【Survived】幸存:表明乘客是否幸存。0 表示是,1 表示否。
- 【Pclass】P类:3个机票类别之一:1类,2类和3类.
- 【Name】姓名:乘客姓名。
- 【Sex】性别:乘客的性别。
- 【Age】年龄:乘客的年龄(以岁为单位)。
- SibSp:船上的兄弟姐妹或配偶的数量。
- Parch:船上的父母或孩子人数。
- 【Ticket】票:乘客的票号。
- 【Fare】票价:表示票价。
- 【Cabin】客舱:乘客的客舱号码。
- 【Embarked】登船:登船港。
titanic = pd.read_csv("titanic.csv")
titanic.head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 0 | 3 | Braund, Mr. Owen Harris | male | 22.0 | 1 | 0 | A/5 21171 | 7.2500 | NaN | S |
1 | 2 | 1 | 1 | Cumings, Mrs. John Bradley (Florence Briggs Th... | female | 38.0 | 1 | 0 | PC 17599 | 71.2833 | C85 | C |
2 | 3 | 1 | 3 | Heikkinen, Miss. Laina | female | 26.0 | 0 | 0 | STON/O2. 3101282 | 7.9250 | NaN | S |
3 | 4 | 1 | 1 | Futrelle, Mrs. Jacques Heath (Lily May Peel) | female | 35.0 | 1 | 0 | 113803 | 53.1000 | C123 | S |
4 | 5 | 0 | 3 | Allen, Mr. William Henry | male | 35.0 | 0 | 0 | 373450 | 8.0500 | NaN | S |
【空气质量数据】
使用有关以下内容的空气质量数据
以及小于 2.5 微米的颗粒物,由 OpenAQ 提供并使用 py-openaq 包。air_quality_long.csv数据集提供
和
分别位于巴黎、安特卫普和伦敦的 FR04014、BETR801 和伦敦威斯敏斯特测量站的值。
空气质量数据集包含以下列:
- 城市:使用传感器的城市,巴黎、安特卫普或伦敦
- 国家/地区:使用传感器的国家/地区,法国、比利时或英国
- 位置:传感器的 ID,FR04014、BETR801 或伦敦威斯敏斯特
- 参数:传感器测量的参数,其中之一或颗粒物
- 值:测量值
- 单位:测量参数的单位,在本例中为“μg/m³”
DataFrame的索引是日期时间,即测量的datetime。
【注意】空气质量数据以所谓的长格式数据表示形式提供,每个观测值在单独的行上,每个变量在数据表中的单独列上。长/窄格式也称为整洁数据格式.
air_quality = pd.read_csv("air_quality_long.csv", index_col="date.utc", parse_dates=True)
air_quality.head()
city | country | location | parameter | value | unit | |
---|---|---|---|---|---|---|
date.utc | ||||||
2019-06-18 06:00:00+00:00 | Antwerpen | BE | BETR801 | pm25 | 18.0 | µg/m³ |
2019-06-17 08:00:00+00:00 | Antwerpen | BE | BETR801 | pm25 | 6.5 | µg/m³ |
2019-06-17 07:00:00+00:00 | Antwerpen | BE | BETR801 | pm25 | 18.5 | µg/m³ |
2019-06-17 06:00:00+00:00 | Antwerpen | BE | BETR801 | pm25 | 16.0 | µg/m³ |
2019-06-17 05:00:00+00:00 | Antwerpen | BE | BETR801 | pm25 | 7.5 | µg/m³ |
【1】对表行进行排序
我想根据乘客的年龄对泰坦尼克号数据进行排序。
titanic.sort_values(by="Age").head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
803 | 804 | 1 | 3 | Thomas, Master. Assad Alexander | male | 0.42 | 0 | 1 | 2625 | 8.5167 | NaN | C |
755 | 756 | 1 | 2 | Hamalainen, Master. Viljo | male | 0.67 | 1 | 1 | 250649 | 14.5000 | NaN | S |
644 | 645 | 1 | 3 | Baclini, Miss. Eugenie | female | 0.75 | 2 | 1 | 2666 | 19.2583 | NaN | C |
469 | 470 | 1 | 3 | Baclini, Miss. Helene Barbara | female | 0.75 | 2 | 1 | 2666 | 19.2583 | NaN | C |
78 | 79 | 1 | 2 | Caldwell, Master. Alden Gates | male | 0.83 | 0 | 2 | 248738 | 29.0000 | NaN | S |
我想根据舱位等级和年龄降序对泰坦尼克号数据进行排序。
titanic.sort_values(by=["Pclass", "Age"], ascending=False).head()
PassengerId | Survived | Pclass | Name | Sex | Age | SibSp | Parch | Ticket | Fare | Cabin | Embarked | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
851 | 852 | 0 | 3 | Svensson, Mr. Johan | male | 74.0 | 0 | 0 | 347060 | 7.7750 | NaN | S |
116 | 117 | 0 | 3 | Connors, Mr. Patrick | male | 70.5 | 0 | 0 | 370369 | 7.7500 | NaN | Q |
280 | 281 | 0 | 3 | Duane, Mr. Frank | male | 65.0 | 0 | 0 | 336439 | 7.7500 | NaN | Q |
483 | 484 | 1 | 3 | Turkula, Mrs. (Hedwig) | female | 63.0 | 0 | 0 | 4134 | 9.5875 | NaN | S |
326 | 327 | 0 | 3 | Nysveen, Mr. Johan Hansen | male | 61.0 | 0 | 0 | 345364 | 6.2375 | NaN | S |
使用 DataFrame.sort_values()表中的行根据定义的列进行排序。索引将遵循行顺序。
【2】长到宽表格式
使用空气质量数据集的一小部分。我们专注于 N O 2 NO_2 NO2 数据,并且仅使用每个位置的前两个测量值(即每个组的头部)。数据子集将称为no2_subset.
no2 = air_quality[air_quality['parameter'] == "no2"]
no2.head()
city | country | location | parameter | value | unit | |
---|---|---|---|---|---|---|
date.utc | ||||||
2019-06-21 00:00:00+00:00 | Paris | FR | FR04014 | no2 | 20.0 | µg/m³ |
2019-06-20 23:00:00+00:00 | Paris | FR | FR04014 | no2 | 21.8 | µg/m³ |
2019-06-20 22:00:00+00:00 | Paris | FR | FR04014 | no2 | 26.5 | µg/m³ |
2019-06-20 21:00:00+00:00 | Paris | FR | FR04014 | no2 | 24.9 | µg/m³ |
2019-06-20 20:00:00+00:00 | Paris | FR | FR04014 | no2 | 21.4 | µg/m³ |
no2_subset = no2.sort_index().groupby(["location"]).head(2)
no2_subset
city | country | location | parameter | value | unit | |
---|---|---|---|---|---|---|
date.utc | ||||||
2019-04-09 01:00:00+00:00 | Antwerpen | BE | BETR801 | no2 | 22.5 | µg/m³ |
2019-04-09 01:00:00+00:00 | Paris | FR | FR04014 | no2 | 24.4 | µg/m³ |
2019-04-09 02:00:00+00:00 | London | GB | London Westminster | no2 | 67.0 | µg/m³ |
2019-04-09 02:00:00+00:00 | Antwerpen | BE | BETR801 | no2 | 53.5 | µg/m³ |
2019-04-09 02:00:00+00:00 | Paris | FR | FR04014 | no2 | 27.4 | µg/m³ |
2019-04-09 03:00:00+00:00 | London | GB | London Westminster | no2 | 67.0 | µg/m³ |
我希望三个站的值作为彼此相邻的单独列。
no2_subset.pivot(columns="location", values="value")
location | BETR801 | FR04014 | London Westminster |
---|---|---|---|
date.utc | |||
2019-04-09 01:00:00+00:00 | 22.5 | 24.4 | NaN |
2019-04-09 02:00:00+00:00 | 53.5 | 27.4 | 67.0 |
2019-04-09 03:00:00+00:00 | NaN | NaN | 67.0 |
pivot() 函数纯粹是对数据的重塑:每个索引/列组合都需要一个值。
由于 pandas 支持开箱即用地绘制多列,因此从长表格式到宽表格式的转换可以同时绘制不同的时间序列:
no2.head()
city | country | location | parameter | value | unit | |
---|---|---|---|---|---|---|
date.utc | ||||||
2019-06-21 00:00:00+00:00 | Paris | FR | FR04014 | no2 | 20.0 | µg/m³ |
2019-06-20 23:00:00+00:00 | Paris | FR | FR04014 | no2 | 21.8 | µg/m³ |
2019-06-20 22:00:00+00:00 | Paris | FR | FR04014 | no2 | 26.5 | µg/m³ |
2019-06-20 21:00:00+00:00 | Paris | FR | FR04014 | no2 | 24.9 | µg/m³ |
2019-06-20 20:00:00+00:00 | Paris | FR | FR04014 | no2 | 21.4 | µg/m³ |
no2.pivot(columns="location", values="value").plot()
<AxesSubplot:xlabel='date.utc'>
如果未定义索引参数,则使用现有index(行标签)。
【3】数据透视表
我想要平均浓度 N O 2 NO_2 NO2 和 P M 2.5 PM_{2.5} PM2.5 在每个站点中以表格形式出现。
air_quality.pivot_table(
values="value", index="location", columns="parameter", aggfunc="mean"
)
parameter | no2 | pm25 |
---|---|---|
location | ||
BETR801 | 26.950920 | 23.169492 |
FR04014 | 29.374284 | NaN |
London Westminster | 29.740050 | 13.443568 |
在 pivot() 的情况下,数据只是重新排列。当需要聚合多个值(在此特定情况下,不同时间步长上的值)时,可以使用pivot_table()提供有关如何组合这些值的聚合函数(例如平均值)。
数据透视表是电子表格软件中众所周知的概念。如果对每个变量的行/列边距(小计)感兴趣,请将margins参数设置为 True:
air_quality.pivot_table(
values="value",
index="location",
columns="parameter",
aggfunc="mean",
margins=True,
)
parameter | no2 | pm25 | All |
---|---|---|---|
location | |||
BETR801 | 26.950920 | 23.169492 | 24.982353 |
FR04014 | 29.374284 | NaN | 29.374284 |
London Westminster | 29.740050 | 13.443568 | 21.491708 |
All | 29.430316 | 14.386849 | 24.222743 |
如果您想知道,pivot_table()) 确实与 groupby() 直接链接。通过对parameter和location进行分组,可以得出相同的结果:
air_quality.groupby(["parameter", "location"]).mean()
C:\Users\DingJiaxiong\AppData\Local\Temp\ipykernel_368\2980048512.py:1: FutureWarning: The default value of numeric_only in DataFrameGroupBy.mean is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.
air_quality.groupby(["parameter", "location"]).mean()
value | ||
---|---|---|
parameter | location | |
no2 | BETR801 | 26.950920 |
FR04014 | 29.374284 | |
London Westminster | 29.740050 | |
pm25 | BETR801 | 23.169492 |
London Westminster | 13.443568 |
【4】宽幅到长幅
从上一节中创建的宽格式表再次开始,我们使用 reset_index() 向DataFrame添加新索引.
no2_pivoted = no2.pivot(columns="location", values="value").reset_index()
no2_pivoted.head()
location | date.utc | BETR801 | FR04014 | London Westminster |
---|---|---|---|---|
0 | 2019-04-09 01:00:00+00:00 | 22.5 | 24.4 | NaN |
1 | 2019-04-09 02:00:00+00:00 | 53.5 | 27.4 | 67.0 |
2 | 2019-04-09 03:00:00+00:00 | 54.5 | 34.2 | 67.0 |
3 | 2019-04-09 04:00:00+00:00 | 34.5 | 48.5 | 41.0 |
4 | 2019-04-09 05:00:00+00:00 | 46.5 | 59.5 | 41.0 |
我想收集所有空气质量 N O 2 NO_2 NO2 单列测量(长格式)。
no_2 = no2_pivoted.melt(id_vars="date.utc")
no_2.head()
date.utc | location | value | |
---|---|---|---|
0 | 2019-04-09 01:00:00+00:00 | BETR801 | 22.5 |
1 | 2019-04-09 02:00:00+00:00 | BETR801 | 53.5 |
2 | 2019-04-09 03:00:00+00:00 | BETR801 | 54.5 |
3 | 2019-04-09 04:00:00+00:00 | BETR801 | 34.5 |
4 | 2019-04-09 05:00:00+00:00 | BETR801 | 46.5 |
DataFrame上的 pandas.melt() 方法将数据表从宽格式转换为长格式。列标题将成为新创建的列中的变量名称。
解决方案是如何应用 pandas.melt() 的简短版本。该方法会将id_vars中未提及的所有列融化为两列:一列包含列标题名称,一列包含值本身。后一列默认获取名称value.
传递给 pandas.melt() 的参数可以更详细地定义:
no_2 = no2_pivoted.melt(
id_vars="date.utc",
value_vars=["BETR801", "FR04014", "London Westminster"],
var_name="NO_2",
value_name="id_location",
)
no_2.head()
date.utc | NO_2 | id_location | |
---|---|---|---|
0 | 2019-04-09 01:00:00+00:00 | BETR801 | 22.5 |
1 | 2019-04-09 02:00:00+00:00 | BETR801 | 53.5 |
2 | 2019-04-09 03:00:00+00:00 | BETR801 | 54.5 |
3 | 2019-04-09 04:00:00+00:00 | BETR801 | 34.5 |
4 | 2019-04-09 05:00:00+00:00 | BETR801 | 46.5 |
附加参数具有以下效果:
value_vars定义要融合在一起的列
value_name为值列提供自定义列名,而不是默认列名value
var_name为收集列标题名称的列提供自定义列名。否则,它采用索引名称或默认variable
因此,参数 value_name 和 var_name 只是两个生成的列的用户定义名称。要熔化的柱由id_vars和value_vars定义.
【小结】
sort_values支持按一列或多列排序.
pivot函数纯粹是数据的重组,pivot_table支持聚合。
pivot(长格式到宽格式)的反面是melt(宽格式到长格式)。