本次5个城市10年到15年的PM2.5收集数据来自kaggle:PM2.5 Data of Five Chinese Cities | KaggleMeasurements for Shenyang, Chengdu, Beijing, Guangzhou, and Shanghaihttps://www.kaggle.com/datasets/uciml/pm25-data-for-five-chinese-cities
数据分析小练手:
1、北京PM2.5美国数据和中国观测站数据对比
2、统计使用美国数据,绘制出北京、上海、广州、成都、沈阳5个城市的PM2.5随时间的变化情况
第一个问题比较简单,第二个问题可以在第一个问题的基础上做。
拿到数据后先info一下,看一下数据有哪些列,每列数据有没有缺失的。pandas默认没有输出全部的列,只会输出头尾几列,在输出前设置pandas.set_option('display.max_column', None)就会输出所有列。
全部有52584行数据,拿PM_Dongsi做为中国观测站的数据,但是PM_Dongsi观测站的数据只有25052条,而PM_US Post的数据有50387条,俩个不同观测数据的数据量不同,所以最后在绘图的时候需要选择数据齐全的一个做标准。
确定好目标是要统计出PM2.5随时间的变化情况,拿到有效的数据量也不是很少,所以用折线图。
既然是要依据时间变化排序,所以要用pandas的时间序列datetime,因为表格把时间拆分成了4列,而不是直接给一列时间数据,所以需要把分开的时间字符串用PeriodIndex连接成pandas时间类型datetime。
然后就是对时间序列进行排序采样,表格中给的是每一个小时一行数据,绘制在表格上就需要进行降采样。(重采样前需要先把pandas时间类型先设置为该表的索引,才能进行重采样。重采样:指的是将时间序列从一个频率转化为另一个频率进行处理的过程,将高频率数据转化为低频率数据为降采样,低频率转化为高频率为升采样)
取7天的平均值后会有313行数据(pandas的mean()会跳过Nan去计算平均值,这里不像numpy数组中一样,numpy中计算整行或列的平均值或中位数时,遇到nan类型的数据不会跳过,而是直接给出平均值为nan,对numpy中的nan类型数据需要进行处理,比如删除dropna或者取该列的平均值或中位数替换)
格式化pandas的时间类型可以用strftime()加格式化参数。绘制在X轴的上的刻度太多,再取步长10。最后会发现绘制出来的图中PM_Dongsi只有后面一部分,原因是这一列的数据本身10年到13年1月份前就是没有数据的,为Nan。
import pandas
from matplotlib import pyplot
from matplotlib import font_manager
import re
"""绘制出北京、上海、广州、成都、沈阳5个城市的PM2.5随时间的变化情况"""
bj_data = pandas.read_csv(r'D:\python数据分析\PM25\BeijingPM20100101_20151231.csv', engine='python', encoding='utf-8')
pandas.set_option('display.max_column', None)
my_font = font_manager.FontProperties(fname='C:/WINDOWS/FONTS/MSYH.TTC', size=15)
"""北京PM2.5美国数据和中国观测站数据对比"""
# 把分开的时间字符串用periodIndex连接成pandas时间类型datetime
bj_data['datetime'] = pandas.PeriodIndex(year=bj_data['year'],month=bj_data['month'],day=bj_data['day'],hour=bj_data['hour'], freq='D')
bj_data.set_index('datetime', inplace=True)
# 进行降采样
bj = bj_data.resample('7D').mean() # 取7天的平均数后有313行数据(pandas的mean()会跳过Nan计算平均值)
cn_data = bj['PM_Dongsi']
us_data = bj['PM_US Post']
cn_x = [i.strftime('%Y%m%d') for i in cn_data.index]
cn_y = cn_data.values
us_x = [i.strftime('%Y%m%d') for i in us_data.index]
us_y = us_data.values
pyplot.figure(figsize=(20, 10), dpi=80)
pyplot.plot(range(len(cn_x)), cn_y, label='CN_Data')
pyplot.plot(range(len(us_x)), us_y, label='US_Data')
# 描绘x轴刻度的值不能是拿缺失的数据
pyplot.xticks(range(0, len(cn_x), 10), list(cn_x)[::10], rotation=30)
pyplot.grid(alpha=0.4)
pyplot.xlabel('时间日期', fontproperties=my_font)
pyplot.ylabel('PM2.5的7天平均值', fontproperties=my_font)
pyplot.title('北京PM2.5美国数据和中国观测站数据对比情况', fontproperties=my_font)
pyplot.legend()
pyplot.show()
第二个问题统计5个城市的数据,有5个表格,可以把5个文件的地址放进列表遍历,每次遍历用正则取出文件名中的地址做为一条折线的label就行。统一用PM_US Post这一列的数据。(优化一下可以把xticks放在循环外面做,不用每次循环都取绘制X轴)
全部代码:
import pandas
from matplotlib import pyplot
from matplotlib import font_manager
import re
"""绘制出北京、上海、广州、成都、沈阳5个城市的PM2.5随时间的变化情况"""
# bj_data = pandas.read_csv(r'D:\python数据分析\PM25\BeijingPM20100101_20151231.csv', engine='python', encoding='utf-8')
bj_file_path = r'D:\python数据分析\PM25\BeijingPM20100101_20151231.csv'
sh_file_path = r'D:\python数据分析\PM25\ShanghaiPM20100101_20151231.csv'
gz_file_path = r'D:\python数据分析\PM25\GuangzhouPM20100101_20151231.csv'
cd_file_path = r'D:\python数据分析\PM25\ChengduPM20100101_20151231.csv'
sy_file_path = r'D:\python数据分析\PM25\ShenyangPM20100101_20151231.csv'
pandas.set_option('display.max_column', None)
my_font = font_manager.FontProperties(fname='C:/WINDOWS/FONTS/MSYH.TTC', size=15)
"""北京PM2.5美国数据和中国观测站数据对比"""
# # 把分开的时间字符串用periodIndex连接成pandas时间类型datetime
# bj_data['datetime'] = pandas.PeriodIndex(year=bj_data['year'],month=bj_data['month'],day=bj_data['day'],hour=bj_data['hour'], freq='D')
# bj_data.set_index('datetime', inplace=True)
# # 进行降采样
# bj = bj_data.resample('7D').mean() # 取7天的平均数后有313行数据(pandas的mean()会跳过Nan计算平均值)
# cn_data = bj['PM_Dongsi']
# us_data = bj['PM_US Post']
#
# cn_x = [i.strftime('%Y%m%d') for i in cn_data.index]
# cn_y = cn_data.values
# us_x = [i.strftime('%Y%m%d') for i in us_data.index]
# us_y = us_data.values
# pyplot.figure(figsize=(20, 10), dpi=80)
# pyplot.plot(range(len(cn_x)), cn_y, label='CN_Data')
# pyplot.plot(range(len(us_x)), us_y, label='US_Data')
# # 描绘x轴刻度的值不能是拿缺失的数据
# pyplot.xticks(range(0, len(cn_x), 10), list(cn_x)[::10], rotation=30)
# pyplot.grid(alpha=0.4)
# pyplot.xlabel('时间日期', fontproperties=my_font)
# pyplot.ylabel('PM2.5的7天平均值', fontproperties=my_font)
# pyplot.title('北京PM2.5美国数据和中国观测站数据对比情况', fontproperties=my_font)
# pyplot.legend()
# pyplot.show()
"""统计使用美国数据,绘制出北京、上海、广州、成都、沈阳5个城市的PM2.5随时间的变化情况"""
file_path_list = [bj_file_path, sh_file_path, gz_file_path, cd_file_path, sy_file_path]
pyplot.figure(figsize=(20, 10), dpi=80)
for file_path in file_path_list:
city_data = pandas.read_csv(file_path, engine='python', encoding='utf-8')
city_data['datetime'] = pandas.PeriodIndex(year=city_data['year'], month=city_data['month'],
day=city_data['day'], hour=city_data['hour'], freq='D')
city_data.set_index('datetime', inplace=True)
df = city_data.resample('7D').mean() # 降采样(取7天的平均值)
x = [i.strftime('%Y%m%d') for i in df['PM_US Post'].index]
y = df['PM_US Post'].values
ss = file_path.split('\\')[-1]
pattern = re.compile(r'.+PM')
city_name = pattern.findall(ss)[0].split('PM')[0] # 城市名称
pyplot.plot(range(len(x)), y, label=city_name)
pyplot.xticks(range(0, len(x), 10), list(x)[::10], rotation=30)
pyplot.grid(alpha=0.4)
pyplot.xlabel('时间日期', fontproperties=my_font)
pyplot.ylabel('PM2.5的7天平均值', fontproperties=my_font)
pyplot.title('5个城市PM2.5美国数据随时间的变化情况', fontproperties=my_font)
pyplot.legend(loc='best')
pyplot.show()
可以看出中国5个城市每年年末的时候PM2.5的指数是每年中最高的,最低基本都在每年的6、7月份。