大家好,我是欧K~
本期给大家分享《Python实战系列》的第三篇文章:不规则数据统计分析,该系列主要来自粉丝的实际问题,后期会不断更新,希望对你有所帮助,如有疑问或者需要改进的地方可以私信小编。
第一期:【Python实战系列<一> | 正则提取数据并绘图】
第二期:【Python实战系列<二> | 70万+条表格信息标记】 任务描述: 数据处理并完成绘图:12 个站点平均的逐月 PM2.5浓度变化曲线。
注意事项:这些数据里-999 表示缺测。一个月 30 天的数据里至少要有 20 天有有效数据,如果有效数据小于 20 天,那这个月的平均也就设置为缺测。
文件结构:
文件内容:
🏳️🌈 1. 读取数据
df = pd.read_csv('./datas/Y2014/1001A.txt')
数据格式乍一看很规则,实际第一行和后面是不一样的:
第一行:
YYYY-MM-DD , PM25(ug/m3) , PM10(ug/m3) , SO2(ug/m3) , NO2(ug/m3) , O3(ug/m3) , DailyO8h(ug/m3) , CO(ug/m3) , MDA8(ug/m3)
第n行:
Y2014-01-01 60.611 150.381 44.375 75.000 14.667 16.696 2679.167 45.201
我们先按正常格式读取,然后再单独处理后面的数据,至少表头是正常的,后面可以用上。 🏳️🌈 2. 取数据表的第一列读取后我们看到数据都集中在了第一列,我们将这一列取出来处理:
datas = df['YYYY-MM-DD '].tolist()
这样看起来就好处理多了。
🏳️🌈 3. 正则拆分数据
第2步后我们把数据转换成列表,每一行数中间的空格数量不一定,直接用split分割的话会导致长度不一致,所以这里我们用正则表达式分割:
pd.DataFrame(df['YYYY-MM-DD '].map(lambda x: re.split('\s+', x)).tolist())
这样数据就正常了,然后我们再把原来的表头加上去,就是正常的数据格式了:
🏳️🌈 4. 提取月份数据
我们要统计每年每月平均值,所以这里我们把月份提取出来:
# 第一列数据切割 df_tmp['YYYY-MM-DD '] = df_tmp['YYYY-MM-DD '].str[1:] # 转换成时间类型,提取月份 df_tmp['MM'] = pd.to_datetime(df_tmp['YYYY-MM-DD ']).dt.month # 数据类型转换 df_tmp[' PM25(ug/m3) '] = df_tmp[' PM25(ug/m3) '].astype('float')
🏳️🌈 5. 按月统计这里需要注意一点,正常情况下我们按年、月分组求平均值就可以了,但是这里不可以!我们再看一眼任务要求:这些数据里-999 表示缺测。一个月 30 天的数据里至少要有 20 天有有效数据,如果有效数据小于 20 天,那这个月的平均也就设置为缺测。我们还需要统计缺失数据-999的情况!我们看一下是否有缺失超过10天的情况:
for i in range(1,13): df_mon = df_tmp[df_tmp['MM'] == i] print(i,df_mon[df_mon[' PM25(ug/m3) '] == -999].shape[0]) # 1 4 # 2 6 # 3 0 # 4 0 # 5 2 # 6 0 # 7 11 # 8 0 # 9 0 # 10 3 # 11 0 # 12 3
7月份有11天缺失。。。那么我们只能遍历去统计了:
for i in range(1,13): mean_val = 0 df_mon = df_tmp[df_tmp['MM'] == i] if df_mon[df_mon[' PM25(ug/m3) '] == -999].shape[0]<=10: df_mon = df_mon[df_mon[' PM25(ug/m3) '] != -999] mean_val = df_mon[' PM25(ug/m3) '].mean() mean_vals.append(mean_val)
最后结果:
然后再mean()一下就可以了。
🏳️🌈 6. 绘图
绘图部分比较简单,我们还用比较熟悉的pyecharts绘图,之前的文章介绍的比较多,这里就不详细介绍了,代码如下:
line = ( Line() .add_xaxis(x_data1) .add_yaxis("", y_data1, is_smooth=True,label_opts=opts.LabelOpts(is_show=False)) .set_global_opts( xaxis_opts=opts.AxisOpts( name='date', axislabel_opts=opts.LabelOpts(rotate=30) ), yaxis_opts=opts.AxisOpts(name='ug/m3'), title_opts=opts.TitleOpts(title="AVG_PM25") ) )
效果:
END
以上就是本期为大家整理的全部内容了,喜欢的朋友可以点赞、点在看也可以分享让更多人知道。