数据分析-Pandas如何重塑数据表
数据表,时间序列数据在数据分析建模中很常见,例如天气预报,空气状态监测,股票交易等金融场景。数据分析过程中重新调整,重塑数据表是很重要的技巧,此处选择Titanic数据,以及巴黎、伦敦欧洲城市空气质量监测 N O 2 NO_2 NO2数据作为样例。
GPT专栏文章:
样例程序代码,需要可获取:
样例分析数据,需要可获取:
数据重排列
拿到表格数据后,很多情况下不能直接就用,还需要对数据进行加工处理。数据加工之前,数据的探查就很重要,最常见的是想把表格的某个属性重新按值的大小排列,看有没有什么特点。
比如在Titanic数据中,想把年龄排序查看下年龄分布特征。可以这样操作:
            
            
              python
              
              
            
          
          In [1]: titanic.sort_values(by="Age").head()
Out[1]: 
     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]有或者,还想联合乘客座舱的等级和年龄,看看不同座舱的分布规律。可以排列多个属性,以列表形式。如下所示:
            
            
              python
              
              
            
          
          In [2]: titanic.sort_values(by=['Pclass', 'Age'], ascending=False).head()
Out[2]: 
     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(),通过指定列名进行表格数据重排。
单列延展宽表
例如,需要关注不同监测站的 N O 2 NO_2 NO2监测值随时间变化情况,就重排表格,把数据进行延展。以下为图示

为了方便起见,仅空气质量数据表的一个子集,仅关注 N O 2 NO_2 NO2监测值,且也值关注每个监测站的前2个数据情况。
比如no2_subset只保留 N O 2 NO_2 NO2监测值,需Paris 、London和 Antwerpen的前两个记录,结果如下:
            
            
              python
              
              
            
          
          # filter for no2 data only
In [3]: no2 = air_quality[air_quality["parameter"] == "no2"]
# use 2 measurements (head) for each location (groupby)
In [3]: no2_subset = no2.sort_index().groupby(["location"]).head(2)
In [4]: no2_subset
Out[4]: 
                                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]那么,每个监测站分别作为一个独立的属性列,可以使用pivot函数,这样操作:
            
            
              python
              
              
            
          
          In [5]: no2_subset.pivot(columns="location", values="value")
Out[5]: 
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.0pivot()函数就是纯粹重排数据的,每列一个值。
pandas支持画不同列数据在同一张图上,共用相同的时间轴。
            
            
              python
              
              
            
          
          In [6]: no2.head()
Out[6]: 
                            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 [7]: no2.pivot(columns="location", values="value").plot()
Out[7]: <AxesSubplot: xlabel='date.utc'>如果需要分析每个监测站的 N O 2 NO_2 NO2监测值和 P M 2.5 PM_{2.5} PM2.5监测值的平均浓度。pivot只是重排表格,需要多值的重新聚合,pivot_table()函数就比较合适,提供聚合函数的功能。
            
            
              python
              
              
            
          
          In [8]: air_quality.pivot_table(
   ....:     values="value", index="location", columns="parameter", aggfunc="mean"
   ....: )
   ....: 
Out[8]: 
parameter                 no2       pm25
location                                
BETR801             26.950920  23.169492
FR04014             29.374284        NaN
London Westminster  29.740050  13.443568就是熟悉的数据透视表功能。通常对行、列的聚合感兴趣。
            
            
              python
              
              
            
          
          In [9]: air_quality.pivot_table(
   ....:     values="value",
   ....:     index="location",
   ....:     columns="parameter",
   ....:     aggfunc="mean",
   ....:     margins=True,
   ....: )
   ....: 
Out[9]: 
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()函数功能,获得相同的结果。
            
            
              python
              
              
            
          
          air_quality.groupby(["parameter", "location"]).mean()宽表聚到单列
相反的,如果想把宽表合道一个列里头,又该怎么办?

开始之前,先把表格弄成左边图的样子,用前面的知识。
            
            
              python
              
              
            
          
          In [10]: no2_pivoted = no2.pivot(columns="location", values="value").reset_index()
In [11]: no2_pivoted.head()
Out[11]: 
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监测值给我堆成一列。老板:不要问为什么!不用喷他,直接show结果,代码如下:
            
            
              python
              
              
            
          
          In [12]: no_2 = no2_pivoted.melt(id_vars="date.utc")
In [13]: no_2.head()
Out[13]: 
                   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用melt()就能妥妥的完成任务,从宽表汇聚成1列,搞定。
如果遇到强迫症,需要把列名称和原来列属性更换名字,就还可以做的更好:
            
            
              python
              
              
            
          
          In [15]: no_2 = no2_pivoted.melt(
   ....:     id_vars="date.utc",
   ....:     value_vars=["BETR801", "FR04014", "London Westminster"],
   ....:     value_name="NO_2",
   ....:     var_name="id_location",
   ....: )
   ....: 
In [16]: no_2.head()
Out[16]: 
                   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以上代码只是一个简单示例,示例代码中的表达式可以根据实际问题进行修改。
样例程序代码,需要可获取:
样例分析数据,需要可获取:
觉得有用 收藏 收藏 收藏
点个赞 点个赞 点个赞
End
GPT专栏文章:
GPT实战系列-ChatGLM3本地部署CUDA11+1080Ti+显卡24G实战方案
GPT实战系列-LangChain + ChatGLM3构建天气查询助手
GPT实战系列-大模型为我所用之借用ChatGLM3构建查询助手
GPT实战系列-P-Tuning本地化训练ChatGLM2等LLM模型,到底做了什么?(二)
GPT实战系列-P-Tuning本地化训练ChatGLM2等LLM模型,到底做了什么?(一)
GPT实战系列-ChatGLM2部署Ubuntu+Cuda11+显存24G实战方案