实战内容:利用pandas以及数据可视化对比中美统计的PM2.5数据


首先打印一下数据信息,查看数据结构

= "./BeijingPM20100101_20151231.csv"
df = pd.read_csv(file_path)
print(df.head())
print(df.info())

前5行数据如下:

pandas实战(PM2.5)_数据结构


数据的详细信息如下:

pandas实战(PM2.5)_时间间隔_02


我们将时间数据进行合并,并将得到的新的时间添加到数据中,并将时间设置为索引,以便画图时使用

# 观察数据,我们可以知道csv文件中的时间间隔为一小时,故将采样频率设置为"H"
period = pd.PeriodIndex(year=df["year"], month=df["month"], day=df["day"], hour=df["hour"], freq="H")
df["datetime"] = period
df.set_index("datetime", inplace=True)

现在我们要取得PM_US Post作为y轴数据画图

= df["PM_US Post"]
x = data.index
y = data.values
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(range(len(x)), y)
plt.show()

画图结果:

pandas实战(PM2.5)_数据结构_03


emmmm,惨不忍睹,数据太密集了,而且若前半部分数据大部分是NaN,后半部分基本没有NaN,直接dropna会导致时间很不均匀。

现在重新采样,将时间间隔设置为7天(也就是原7*24=148条数据整合成1条数据),同时将这7天的PM2.5数据取平均值作为采样数据

df = df.resample("7D").mean()

直接画图

= data.index
x = [i.strftime("%Y-%m-%d") for i in x]
y = data.values
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(range(len(x)), y)
plt.xticks(range(0, len(x), 10), list(x)[::10], rotation=45)
plt.show()

降采样后的结果:

pandas实战(PM2.5)_时间间隔_04

我们对比一下中美检测PM2.5,取"PM_Dongsi"作为中国的数据画图

= data_cn.index
x_cn = [i.strftime("%Y-%m-%d") for i in x_cn]
y_cn = data_cn.values
plt.plot(range(len(x_cn)), y_cn, label="CN_POST")

pandas实战(PM2.5)_时间间隔_05


由于中国统计的数据从2010-01-01到2013-01-04全是NaN,所以前半部分没有橙色的线条

完整代码:

import pandas as pd
from matplotlib import pyplot as plt


def main():
file_path = "./BeijingPM20100101_20151231.csv"
df = pd.read_csv(file_path)
# print(df.head(1)[["PM_Dongsi","PM_Dongsihuan"]])
# print(df.info())
# 把分开的时间字符串通过PeriodIndex方法转化为pandas的时间类型
period = pd.PeriodIndex(year=df["year"], month=df["month"], day=df["day"], hour=df["hour"], freq="H")
df["datetime"] = period
# 将datetime设置为索引
df.set_index("datetime", inplace=True)
# 进行降采样
df = df.resample("7D").mean()
data = df["PM_US Post"] # 取出PM_US Post列,然后删除含有NaN的数据
data_cn = df["PM_Dongsi"]
x = data.index
x_cn = data_cn.index
x = [i.strftime("%Y-%m-%d") for i in x]
x_cn = [i.strftime("%Y-%m-%d") for i in x_cn]
y = data.values
y_cn = data_cn.values
plt.figure(figsize=(20, 8), dpi=80)
plt.plot(range(len(x)), y, label="US_POST")
plt.plot(range(len(x_cn)), y_cn, label="CN_POST")
plt.xticks(range(0, len(x), 10), list(x)[::10], rotation=45)
plt.legend(loc="best")
plt.savefig(fname="./1.png", dpi=500)
plt.show()


if __name__ == '__main__':
main()