In [1]: import pandas as pd
- 泰坦尼克号数据
本教程使用泰坦尼克号数据集,存储为 CSV。数据包含以下数据列
PassengerId:每个乘客的 ID。
Survived:指示乘客是否幸存。
0
表示是,1
表示否。Pclass:3 个票价等级之一:等级
1
、等级2
和等级3
。Name:乘客姓名。
Sex:乘客性别。
Age:乘客年龄(以年为单位)。
SibSp:船上兄弟姐妹或配偶的人数。
Parch:船上父母或子女的人数。
票号:乘客的票号。
票价:表示票价。
客舱:乘客的客舱号。
登船港口:登船港口。
In [2]: titanic = pd.read_csv("data/titanic.csv") In [3]: titanic.head() Out[3]: PassengerId Survived Pclass ... Fare Cabin Embarked 0 1 0 3 ... 7.2500 NaN S 1 2 1 1 ... 71.2833 C85 C 2 3 1 3 ... 7.9250 NaN S 3 4 1 1 ... 53.1000 C123 S 4 5 0 3 ... 8.0500 NaN S [5 rows x 12 columns]
-
空气质量数据
本教程使用由 OpenAQ 提供的关于 \(NO_2\) 和小于 2.5 微米的颗粒物的空气质量数据,并使用 py-openaq 包。
air_quality_long.csv
数据集分别为巴黎、安特卫普和伦敦的 FR04014、BETR801 和 伦敦威斯敏斯特 测量站提供了 \(NO_2\) 和 \(PM_{25}\) 值。空气质量数据集包含以下列
城市:传感器使用所在的城市,巴黎、安特卫普或伦敦
国家:传感器使用所在的国家,FR、BE 或 GB
位置:传感器的 ID,FR04014、BETR801 或 伦敦威斯敏斯特
参数:传感器测量的参数,\(NO_2\) 或颗粒物
值:测量的值
单位:测量参数的单位,在本例中为 ‘µg/m³’
以及
DataFrame
的索引为datetime
,即测量的时间。注意
空气质量数据以所谓的长格式数据表示形式提供,每个观测值在单独的行上,每个变量在数据表的单独列中。长/窄格式也称为 整洁数据格式。
In [4]: air_quality = pd.read_csv( ...: "data/air_quality_long.csv", index_col="date.utc", parse_dates=True ...: ) ...: In [5]: air_quality.head() Out[5]: 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³
如何重塑表格的布局#
排序表格行#
我想根据乘客的年龄对泰坦尼克号数据进行排序。
In [6]: titanic.sort_values(by="Age").head() Out[6]: PassengerId Survived Pclass ... Fare Cabin Embarked 803 804 1 3 ... 8.5167 NaN C 755 756 1 2 ... 14.5000 NaN S 644 645 1 3 ... 19.2583 NaN C 469 470 1 3 ... 19.2583 NaN C 78 79 1 2 ... 29.0000 NaN S [5 rows x 12 columns]
我想根据客舱等级和年龄降序对泰坦尼克号数据进行排序。
In [7]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head() Out[7]: PassengerId Survived Pclass ... Fare Cabin Embarked 851 852 0 3 ... 7.7750 NaN S 116 117 0 3 ... 7.7500 NaN Q 280 281 0 3 ... 7.7500 NaN Q 483 484 1 3 ... 9.5875 NaN S 326 327 0 3 ... 6.2375 NaN S [5 rows x 12 columns]
使用
DataFrame.sort_values()
,表格中的行将根据定义的列进行排序。索引将遵循行顺序。
有关表格排序的更多详细信息,请参阅用户指南中关于 排序数据 的部分。
长表到宽表格式#
让我们使用空气质量数据集的一个小子集。我们关注 \(NO_2\) 数据,并且只使用每个位置的前两个测量值(即每个组的头部)。该数据集的子集将被称为 no2_subset
。
# filter for no2 data only
In [8]: no2 = air_quality[air_quality["parameter"] == "no2"]
# use 2 measurements (head) for each location (groupby)
In [9]: no2_subset = no2.sort_index().groupby(["location"]).head(2)
In [10]: no2_subset
Out[10]:
city country ... value unit
date.utc ...
2019-04-09 01:00:00+00:00 Antwerpen BE ... 22.5 µg/m³
2019-04-09 01:00:00+00:00 Paris FR ... 24.4 µg/m³
2019-04-09 02:00:00+00:00 London GB ... 67.0 µg/m³
2019-04-09 02:00:00+00:00 Antwerpen BE ... 53.5 µg/m³
2019-04-09 02:00:00+00:00 Paris FR ... 27.4 µg/m³
2019-04-09 03:00:00+00:00 London GB ... 67.0 µg/m³
[6 rows x 6 columns]
我希望将三个站点的值作为单独的列彼此相邻。
In [11]: no2_subset.pivot(columns="location", values="value") Out[11]: 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 支持对多个列进行绘图(参见 绘图教程),因此从长到宽表格格式的转换使得能够同时绘制不同的时间序列。
In [12]: no2.head()
Out[12]:
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³
In [13]: no2.pivot(columns="location", values="value").plot()
Out[13]: <Axes: xlabel='date.utc'>
注意
当 index
参数未定义时,将使用现有索引(行标签)。
有关 pivot()
的更多信息,请参见用户指南中关于 透视 DataFrame 对象 的部分。
透视表#
我希望以表格形式显示每个站点中 \(NO_2\) 和 \(PM_{2.5}\) 的平均浓度。
In [14]: air_quality.pivot_table( ....: values="value", index="location", columns="parameter", aggfunc="mean" ....: ) ....: Out[14]: parameter no2 pm25 location BETR801 26.950920 23.169492 FR04014 29.374284 NaN London Westminster 29.740050 13.443568
在
pivot()
的情况下,数据只是重新排列。当需要聚合多个值(在本例中,是不同时间步上的值)时,可以使用pivot_table()
,它提供一个聚合函数(例如平均值)来组合这些值。
透视表是电子表格软件中一个众所周知的概念。当对每个变量的行/列边际(小计)感兴趣时,将 margins
参数设置为 True
。
In [15]: air_quality.pivot_table(
....: values="value",
....: index="location",
....: columns="parameter",
....: aggfunc="mean",
....: margins=True,
....: )
....:
Out[15]:
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()
的更多信息,请参见用户指南中关于 透视表 的部分。
注意
如果您想知道,pivot_table()
确实直接与 groupby()
相关联。通过对 parameter
和 location
进行分组,可以得到相同的结果。
air_quality.groupby(["parameter", "location"])[["value"]].mean()
宽格式到长格式#
从上一节中创建的宽格式表格开始,我们使用 reset_index()
为 DataFrame
添加一个新的索引。
In [16]: no2_pivoted = no2.pivot(columns="location", values="value").reset_index()
In [17]: no2_pivoted.head()
Out[17]:
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
我想将所有空气质量 \(NO_2\) 测量值收集到一个单独的列中(长格式)。
In [18]: no_2 = no2_pivoted.melt(id_vars="date.utc") In [19]: no_2.head() Out[19]: 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()
的参数可以更详细地定义。
In [20]: no_2 = no2_pivoted.melt(
....: id_vars="date.utc",
....: value_vars=["BETR801", "FR04014", "London Westminster"],
....: value_name="NO_2",
....: var_name="id_location",
....: )
....:
In [21]: no_2.head()
Out[21]:
date.utc id_location NO_2
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
定义。
用户指南中关于 通过熔化重塑 的部分解释了使用 pandas.melt()
从宽格式转换为长格式。
记住
通过
sort_values
支持按一个或多个列排序。函数
pivot
纯粹是对数据的重构,pivot_table
支持聚合。pivot
的反向(长格式到宽格式)是melt
(宽格式到长格式)。
用户指南中关于 重塑和透视 的页面提供了完整概述。