1. 程式人生 > 其它 >空氣質量分析

空氣質量分析

由於霧霾問題,全社會都很關注空氣質量,政府也花了很多錢力圖改善空氣質量。我們作為城市市民經常要問:我們城市的空氣質量到底怎樣?這幾年我們城市的空氣質量是在改善還是惡化?我們城市的空氣質量與其他城市相比,是更好還是更差?

官方媒體一般都是說:我們的空氣質量在改善,但有資料證明嗎?官方資料可信嗎?我們心存疑慮。所以,作為資料狗,還是自己動手吧。

PM2.5是最近幾年特別熱議的空氣質量指標,這要歸功於美帝大使館哦。美國駐華使館和領館自己檢測PM2.5資料並且在官網釋出,這才讓國人知道了這個指標,後來國內官方也開始公佈這個指標了。

言歸正傳,差點忘了,這是一篇Python技術貼。回到這篇文章的主題:用Python做資料分析。我生活在廣州,當然以我大廣州為分析目標了。

資料來源:美國駐華使館的空氣質量檢測資料, [ http://www.stateair.net/web/historical/1/1.html

](http://www.stateair.net/web/historical/1/1.html) 包含以下欄位:

其中,PM2.5數值所代表的空氣質量評價如下表1-1所示:

在此基礎上,如果指數大於500,就是大家戲稱為“爆表”

問題:

一.廣州的空氣質量總體如何?

二.廣州最近兩年的空氣質量是否有改善?

三.廣州北京兩地的空氣質量對比

這幾個問題其實比較大而空,要落實到具體的指標和維度。從我們掌握的以上資料出發,可以從以下幾個指標和維度分析:

1.2016年全年來看,空氣質量較好(PM2.5<=100)的天數佔比是多少?2015年相比2016年的對比?北京與各自的對比如何?

2.2016年全年來看,空氣質量最嚴重(PM2.5>300)的天數佔比是多少?2015年相比2016年的對比?北京與各自的對比如何?

3.2016年全年來看,空氣質量與季節(月份)的變化關係是什麼?

4.2016年與2015年同時間點對比,空氣質量較好和較差的次數分別是多少?

5.2016年廣州與北京同時間點對比,空氣質量較好和較差的次數分別是多少?

通過以上維度分析,可以基本對前面的三大問題得出大致的判斷。當然,有興趣的童鞋可以根據原始資料出發,從更多的維度進行分析哦。

下面就開始進入資料集吧。

1. 資料集下載、讀取和清洗

從美駐華使館官網下載了廣州、北京兩個城市,2015年和2016年的PM2.5資料。分別是這四個檔案:
Beijing_2015_HourlyPM25_created20160201.csv

Beijing_2016_HourlyPM25_created20170201.csv

Guangzhou_2015_HourlyPM25_created20170201.csv

Guangzhou_2016_HourlyPM25_created20170201.csv

為了簡化工作,每個檔案只保留這幾個欄位:Year、Month、Day、Hour、Value和QC
name,用Excel刪掉其他的欄位和文字,千萬注意要保留表頭哦。

經過大致觀察,可以發現以下幾點:

  1. 資料以csv格式儲存,每年1個檔案
  2. 每個小時一條檢測資料

首先引入必要的Python包

In [1]:

    import unicodecsv
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import seaborn as sb
    
    %matplotlib inline

從csv檔案中讀入資料

pandas是Python中常用的資料分析工具,包含了大量簡便的資料分析處理方法。本文通過這個例子,展現了幾個常用的pandas使用方法。

其中,使用pandas可以很方便地從csc檔案中讀取資料,儲存在DataFrame物件中,方法如下:

In [2]:

    # 從csv中讀取北京2015年pm2.5資料,儲存在DataFrame中
    df_bj2015 = pd.read_csv('data/Beijing_2015_HourlyPM25_created20160201.csv')
    
    # 重新設定各個欄位的名稱
    df_bj2015.columns=['Year','Month','Day','Hour','Value','QC']

資料探索和清洗

拿到資料集,並且匯入了DataFrame物件後,我們需要對資料進行觀察,看看是否有缺失和錯誤的情況,並且對資料集進行必要的清洗處理,以便後續得到更準確的分析結果。

In [3]:

    # 檢視DataFrame中的前幾條資料
    df_bj2015.head()

Out[3]:

Year Month Day Hour Value QC
0 2015 1 1 0 22
1 2015 1 1 1 9
2 2015 1 1 2 9
3 2015 1 1 3 13
4 2015 1 1 4 10

In [4]:

    # DataFrame的簡要描述
    df_bj2015.describe()

Out[4]:

Year Month Day Hour Value
count 8760.0 8760.000000 8760.000000 8760.000000

8760.000000
mean | 2015.0 | 6.526027 | 15.720548 | 11.500114 | 71.658904
std | 0.0 | 3.448048 | 8.796749 | 6.922433 | 139.751292
min | 2015.0 | 1.000000 | 1.000000 | 0.000000 | -999.000000
25% | 2015.0 | 4.000000 | 8.000000 | 5.750000 | 21.000000
50% | 2015.0 | 7.000000 | 16.000000 | 11.500000 | 53.000000
75% | 2015.0 | 10.000000 | 23.000000 | 17.250000 | 108.000000
max | 2015.0 | 12.000000 | 31.000000 | 23.000000 | 722.000000

從簡要描述中,可以看出Value欄位(pm2.5的值)最小值是-999,正常來說,PM2.5的值不會小於零的,這說明有些觀測值是缺失或者記錄錯誤。我們可以計算一下其中有多少Value<0的記錄:

In [5]:

    len(df_bj2015.ix[df_bj2015.Value<0, :])

Out[5]:

    97
[/code]

全年8000多條資料中,只有97條記錄缺失或錯誤,所以把這97條記錄刪除,對整個分析影響不大。以下把缺失或錯誤的記錄刪除:

In [6]:

```code
    # 把錯誤值置為空值
    df_bj2015.loc[df_bj2015.Value<0,'Value']=np.nan
    
    # 刪除空值記錄
    df_bj2015.dropna(inplace=True)

再用describe方法看看資料集的概況:

In [7]:

    df_bj2015.describe()

Out[7]:

Year Month Day Hour Value
count 8663.0 8663.000000 8663.000000 8663.000000

8663.000000
mean | 2015.0 | 6.538728 | 15.674939 | 11.494055 | 82.733810
std | 0.0 | 3.448080 | 8.787195 | 6.938605 | 88.556186
min | 2015.0 | 1.000000 | 1.000000 | 0.000000 | 0.000000
25% | 2015.0 | 4.000000 | 8.000000 | 5.000000 | 21.000000
50% | 2015.0 | 7.000000 | 16.000000 | 11.000000 | 54.000000
75% | 2015.0 | 10.000000 | 23.000000 | 18.000000 | 109.000000
max | 2015.0 | 12.000000 | 31.000000 | 23.000000 | 722.000000

可以看出,Value欄位最小值不再為負數,這樣的資料基本可信。

另外,我們還要為資料集增加一個欄位,根據前面表1-1的劃分方法,把pm2.5的測量值Value,轉換為空氣質量等級。
首先,我們先寫一個函式,通過pm2.5測量值對應的空氣質量等級。

In [8]:

    df_bj2015.describe()

Out[8]:

Year Month Day Hour Value
count 8663.0 8663.000000 8663.000000 8663.000000

8663.000000
mean | 2015.0 | 6.538728 | 15.674939 | 11.494055 | 82.733810
std | 0.0 | 3.448080 | 8.787195 | 6.938605 | 88.556186
min | 2015.0 | 1.000000 | 1.000000 | 0.000000 | 0.000000
25% | 2015.0 | 4.000000 | 8.000000 | 5.000000 | 21.000000
50% | 2015.0 | 7.000000 | 16.000000 | 11.000000 | 54.000000
75% | 2015.0 | 10.000000 | 23.000000 | 18.000000 | 109.000000
max | 2015.0 | 12.000000 | 31.000000 | 23.000000 | 722.000000

In [9]:

    def get_grade(value):
        if value <= 50 and value>=0:
            return 'Good'
        elif value <= 100:
            return 'Moderate'
        elif value <= 150:
            return 'Unhealthy for Sensi'
        elif value <= 200:
            return 'Unhealthy'
        elif value <= 300:
            return 'Very Unhealthy'
        elif value <= 500:
            return 'Hazardous'
        elif value > 500:
            return 'Beyond Index'  # 爆表了
        else:
            return None  # 輸入值無效

以下使用DataFrame的apply函式,增加一個欄位‘Grade’,並且根據‘Value’欄位的值,呼叫前面的轉換函式,為‘Grade’欄位賦值。

In [10]:

    df_bj2015.loc[:, 'Grade'] = df_bj2015['Value'].apply(get_grade)

再來看看增加欄位後的資料集

In [11]:

    df_bj2015.head()

Out[11]:

Year Month Day Hour Value QC Grade
0 2015 1 1 0 22.0 Valid
1 2015 1 1 1 9.0 Valid
2 2015 1 1 2 9.0 Valid
3 2015 1 1 3 13.0 Valid
4 2015 1 1 4 10.0 Valid

經過以上的處理,我們就把北京2015年的PM2.5資料集處理完成了。對於其他三個表格,我們都採取類似的處理。

In [12]:

    # 從csv中讀取北京2016年pm2.5資料,儲存在DataFrame中
    df_bj2016 = pd.read_csv('data/Beijing_2016_HourlyPM25_created20170201.csv')
    
    # 重新設定各個欄位的名稱
    df_bj2016.columns=['Year','Month','Day','Hour','Value','QC']
    
    # 對錯誤和缺失值賦為空值
    df_bj2016.loc[df_bj2016.Value<0,'Value']=np.nan
    
    # 刪除空值記錄
    df_bj2016.dropna(inplace=True)
    
    #增加空氣質量等級欄位‘Grade’
    df_bj2016.loc[:, 'Grade'] = df_bj2016['Value'].apply(get_grade)

In [13]:

    df_bj2016.head()

Out[13]:

Year Month Day Hour Value QC Grade
0 2016 1 1 0 231.0 Valid
1 2016 1 1 1 239.0 Valid
2 2016 1 1 2 205.0 Valid
3 2016 1 1 3 167.0 Valid
4 2016 1 1 4 132.0 Valid

In [14]:

    # 從csv中讀取廣州2016年pm2.5資料,儲存在DataFrame中
    df_gz2016 = pd.read_csv('data/Guangzhou_2016_HourlyPM25_created20170201.csv')
    
    # 重新設定各個欄位的名稱
    df_gz2016.columns=['Year','Month','Day','Hour','Value','QC']
    
    # 對錯誤和缺失值賦為空值
    df_gz2016.loc[df_gz2016.Value<0,'Value']=np.nan
    
    # 刪除空值記錄
    df_gz2016.dropna(inplace=True)
    
    #增加空氣質量等級欄位‘Grade’
    df_gz2016.loc[:, 'Grade'] = df_gz2016['Value'].apply(get_grade)

In [15]:

    df_gz2016.head()

Out[15]:

Year Month Day Hour Value QC Grade
0 2016 1 1 0 55.0 Valid
1 2016 1 1 1 58.0 Valid
2 2016 1 1 2 59.0 Valid
3 2016 1 1 3 58.0 Valid
4 2016 1 1 4 51.0 Valid

In [16]:

    # 從csv中讀取廣州2015年pm2.5資料,儲存在DataFrame中
    df_gz2015 = pd.read_csv('data/Guangzhou_2015_HourlyPM25_created20160201.csv')
    
    # 重新設定各個欄位的名稱
    df_gz2015.columns=['Year','Month','Day','Hour','Value','QC']
    
    # 對錯誤和缺失值賦為空值
    df_gz2015.loc[df_gz2015.Value<0,'Value']=np.nan
    
    # 刪除空值記錄
    df_gz2015.dropna(inplace=True)
    
    #增加空氣質量等級欄位‘Grade’
    df_gz2015.loc[:, 'Grade'] = df_gz2015['Value'].apply(get_grade)

In [17]:

    df_gz2015.head()

Out[17]:

Year Month Day Hour Value QC Grade
0 2015 1 1 0 38.0 Valid
1 2015 1 1 1 40.0 Valid
2 2015 1 1 2 40.0 Valid
3 2015 1 1 3 34.0 Valid
4 2015 1 1 4 42.0 Valid

好了,我們已經把本次分析所需的資料集全部準備完畢,接下來就是進行資料的分析

<未完待續>