In [1]: import pandas as pd
Data used for this tutorial:
  • 本教程使用存储为CSV的泰坦尼克号数据集。数据由以下数据列组成:

    • PassengerID:每个乘客的ID。

    • 生还:表示乘客是否生还。 0 是的而且 1 不是的。

    • Pclass:3个票类中的一个:类 1 ,班级 2 和班级 3

    • 姓名:乘客姓名。

    • 性别:乘客性别。

    • 年龄:乘客的年龄,以年为单位。

    • SibSp:船上兄弟姐妹或配偶的数量。

    • Parch:船上父母或孩子的人数。

    • 车票:旅客车票号码。

    • 票价:标明票价。

    • 客舱:客舱人数。

    • 已装船:装船港。

    To raw data
    In [2]: titanic = pd.read_csv("data/titanic.csv")
    
    In [3]: titanic.head()
    Out[3]: 
       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
    
  • 本教程使用的空气质量数据 \(NO_2\) 和小于2.5微米的颗粒物,由 OpenAQ 并使用 py-openaq 包裹。这个 air_quality_long.csv 数据集提供 \(NO_2\)\(PM_{{25}}\) 测量站的值 FR04014BETR801伦敦威斯敏斯特 分别在巴黎、安特卫普和伦敦。

    空气质量数据集包含以下列:

    • 城市:使用传感器的城市,巴黎、安特卫普或伦敦

    • 国家/地区:使用传感器的国家/地区,FR、BE或GB

    • 位置:传感器的ID,或者 FR04014BETR801伦敦威斯敏斯特

    • 参数:传感器测量的参数,可以是 \(NO_2\) 或颗粒物

    • 值:测量值

    • 单位:测量参数的单位,在本例中为“微克/米”。

    和索引中的 DataFramedatetime ,度量的日期时间。

    备注

    空气质量数据是在所谓的 长格式 数据表示法,每个观察值位于数据表的单独行中,每个变量位于数据表的单独列中。长/窄格式也称为 tidy data format

    To raw data
    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                             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
    
  • 我想把泰坦尼克号的数据按照船舱等级和年龄降序排列。

    In [7]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()
    Out[7]: 
         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() 表中的行将根据定义的列进行排序。索引将遵循行顺序。

To user guide

上的用户指南部分提供了有关表排序的更多详细信息 sorting data

长到宽的表格格式#

让我们使用空气质量数据集的一小部分。我们专注于 \(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            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³
../../_images/07_pivot.svg
  • 我想要三个站点的值作为彼此相邻的单独列。

    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支持绘制多个列(请参见 plotting tutorial )开箱即用,从 longwide 表格格式允许同时绘制不同的时间序列:

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]: <AxesSubplot:xlabel='date.utc'>
../../_images/7_reshape_columns.png

备注

index 参数,则使用现有索引(行标签)。

To user guide

有关以下内容的更多信息 pivot() ,请参阅上的用户指南部分 pivoting DataFrame objects

数据透视表#

../../_images/07_pivot_table.svg
  • 我想要平均浓度 \(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
To user guide

有关以下内容的更多信息 pivot_table() ,请参阅上的用户指南部分 pivot tables

备注

如果你想知道的话, pivot_table() 确实直接与 groupby() 。通过对两者进行分组可以得出相同的结果 parameterlocation

air_quality.groupby(["parameter", "location"]).mean()
To user guide

看一看 groupby() 结合使用 unstack() 在上的用户指南部分 combining stats and groupby

从宽到长格式#

再次从上一节中创建的宽格式表开始,我们向 DataFrame 使用 reset_index()

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
../../_images/07_melt.svg
  • 我想收集所有的空气质量 \(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
    

    这个 pandas.melt() 对象上的方法 DataFrame 将数据表从宽格式转换为长格式。列标题将成为新创建的列中的变量名。

解决方案是关于如何应用的简短版本 pandas.melt() 。该方法将 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 定义要将哪些列 melt 同舟共济

  • value_name provides a custom column name for the values column instead of the default column name value

  • var_name provides a custom column name for the column collecting the column header names. Otherwise it takes the index name or a default variable

因此,这些争论 value_namevar_name 只是用户为两个生成的列定义的名称。要融化的柱由 id_varsvalue_vars

To user guide

使用将宽格式转换为长格式 pandas.melt() 上的用户指南部分对此进行了说明 reshaping by melt

REMEMBER

  • 支持按一列或多列排序 sort_values

  • 这个 pivot 功能是纯粹的数据重组, pivot_table 支持聚合。

  • 的反面 pivot (长至宽格式)是 melt (宽到长格式)。

To user guide

有关以下页面的用户指南中提供了完整的概述 reshaping and pivoting