開始之前簡單交代一下背景拳氢,我研究生導師在全國做掛面干燥項目践剂,不同地方的氣候對掛面干燥工藝有一定影響弓摘,因此經常需要我?guī)兔y(tǒng)計國內某城市一年的溫濕度變化情況圣蝎。以前用excle表格ctrl+C刃宵、ctrl+V方式得到一個城市的某年溫濕度表,這種方式重復性操作多徘公,而且查找數(shù)據(jù)麻煩牲证。在學習了python后,決定做一個一勞永逸的繪制溫濕度的腳本关面。
本文分以下幾個方面介紹:
- 原始數(shù)據(jù)獲取
- 應用pandas對原始數(shù)據(jù)篩選坦袍、整理
- 應用matplotlab繪制數(shù)據(jù)圖像
一、原始數(shù)據(jù)獲取
原始數(shù)據(jù)從中國氣象數(shù)據(jù)中心地面資料下載獲取等太,數(shù)據(jù)說明可在網站上找到相關文檔捂齐。加載需自己需要的數(shù)據(jù)后,幾個小時后可以從訂單中下載數(shù)據(jù)缩抡。數(shù)據(jù)格式是.txt的文件辛燥,文件里面有每個月的下載地址(每個月都有單獨一個下載地址)。在linux操作系統(tǒng)中,使用wget工具批量下載數(shù)據(jù):
wget -i S201806271736073722600.txt -P tem
獲得2019年全國主要城市的溫濕度數(shù)據(jù)文件挎塌,文件名中含有RHU是相對濕度數(shù)據(jù),含有TEM的是溫度數(shù)據(jù)内边。每個文件名都標有年份和月份日期榴都,如201902。
濕度數(shù)據(jù)一共有11列漠其,其中第一列是城市編碼嘴高,官網下載文件查詢編碼對應城市,其余每列數(shù)據(jù)代表查詢如圖濕度數(shù)據(jù)每列對應表和屎。
同理拴驮,溫度數(shù)據(jù)一共是13列,每列數(shù)據(jù)含義也可查詢柴信。
到此原始數(shù)據(jù)已經獲取完畢套啤。
二、應用pandas對原始數(shù)據(jù)篩選随常、整理
1.遍歷原始數(shù)據(jù)文件
應用golb工具潜沦,遍歷文件夾內所有文件名,并將文件名存入list中:
for month in range(1, 13):
if month < 10:
list_tem = glob.glob(raw_data_path + '/*TEM*20190' + str(month) + '*')
list_rhu = glob.glob(raw_data_path + '/*RHU*20190' + str(month) + '*')
else:
list_tem = glob.glob(raw_data_path + '/*TEM*2019' + str(month) + '*')
list_rhu = glob.glob(raw_data_path + '/*RHU*2019' + str(month) + '*')
用pandas按月讀取數(shù)據(jù)绪氛,并將每月數(shù)據(jù)按行拼接唆鸡,注意拼接時需要忽略行索引,設置ignore_index=True枣察。此時讀入的數(shù)據(jù)是一列
tem_data = pd.DataFrame()
for raw_file in list_tem:
tem_data_month = pd.read_table(raw_file, header=None, dtype=str)
tem_data = pd.concat([tem_data, tem_data_month], axis=0, ignore_index=True)
設置列索引標題争占,分別為城市ID、日期序目、最小溫度臂痕、最大溫度、平均溫度宛琅。遍歷數(shù)據(jù)框分別處理每一行數(shù)據(jù)刻蟹,用split()方法按空格將數(shù)據(jù)拆分存入列表,再將每列對應的數(shù)據(jù)分別處理后填入對應列中嘿辟。
tem_data.columns = ['city_id']
tem_data['date'] = None
tem_data['min'] = None
tem_data['max'] = None
tem_data['avg'] = None
list_x = []
for i in tqdm(range(len(tem_data))):
list_x = tem_data['city_id'][i].split() # 分開第i行舆瘪,x列的數(shù)據(jù)。split()默認是以空格等符號來分割红伦,返回一個列表
tem_data['city_id'][i] = list_x[0] # 分割形成的列表英古,并將數(shù)據(jù)填入對應列
# tem_data['data'][i] = time.strptime(' - '.join([list_x[4], list_x[5] , list_x[6]]), "%Y - %m - %d")
tem_data['data'][i] = '-'.join([list_x[4], list_x[5], list_x[6]])
tem_data['min'][i] = float(list_x[9]) / 10
tem_data['avg'][i] = float(list_x[7]) / 10
tem_data['max'][i] = float(list_x[8]) / 10
用同樣方法處理濕度數(shù)據(jù)。
rhu_data = pd.DataFrame()
for raw_file in list_rhu:
rhu_data_month = pd.read_table(raw_file, header=None, dtype=str)
rhu_data = pd.concat([rhu_data, rhu_data_month], axis=0, ignore_index=True) rhu_data.columns = ['city_id']
rhu_data['data'] = None
rhu_data['rhu'] = None
list_x = []
for i in tqdm(range(len(rhu_data))):
list_x = rhu_data['city_id'][i].split()
rhu_data['city_id'][i] = list_x[0]
rhu_data['data'][i] = '-'.join([list_x[4], list_x[5], list_x[6]])
rhu_data['rhu'][i] = list_x[7]
將溫度和濕度數(shù)據(jù)融合昙读。
df = pd.merge(tem_data, rhu_data, how='left', on=['city_id', 'data'])
all_data = pd.concat([all_data, df], axis=0, ignore_index=True)
保存處理后的數(shù)據(jù)
all_data.to_csv(os.path.join(root_path, 'all_data.csv')
三召调、用matplotlab工具繪制溫濕度圖像
讀取城市每天的數(shù)據(jù),并去除數(shù)據(jù)中的未觀測值,(32766為為觀測值唠叛,將未觀測值用前一有效數(shù)值替代)
# city_id = 54618
if city_id in df['city_id']:
day_data = df[df['city_id'] == city_id]
else:
print("沒有該編號對應的城市")
# # print(df.shape)
x = df["data"]
month_min = []
month_max = []
month_avg = []
month_rhu = []
# print(day_data)
min_tem = day_data['min'].values.tolist()
max_tem = day_data['max'].values.tolist()
avg_tem = day_data['avg'].values.tolist()
rhu = day_data['rhu'].values.tolist()
modify_invalid_value(3276.6, avg_tem)
modify_invalid_value(3276.6, min_tem)
modify_invalid_value(3276.6, max_tem)
modify_invalid_value(32766, rhu)
計算月平均值,并將月平均值保存在數(shù)據(jù)框中
days = 0
for day in [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]:
month_min.append(sum(min_tem[days:days + day]) / day)
month_max.append(sum(max_tem[days:days + day]) / day)
month_avg.append(sum(avg_tem[days:days + day]) / day)
month_rhu.append(sum(rhu[days:days + day]) / day)
days = days + day
manth_data = pd.DataFrame(
{"city_id": city_id, "min_tem": month_min, "max_tem": month_max, "avg_tem": month_avg, "avg_rhu": month_rhu})
繪制數(shù)據(jù)只嚣,并保存圖像和結果
months = [month for month in range(1, 13)]
fig, ax1 = plt.subplots()
ax1.plot(months, month_min, label=u"min_Tem")
ax1.plot(months, month_max, label=u"max_Tem")
ax1.plot(months, month_avg, label=u"avg_Tem")
ax2 = ax1.twinx()
ax2.plot(months, month_rhu, '--', label=u"avg_Rhu")
# _xtick_labels_ = [' '.join(time.asctime(time.strptime(i, "%Y-%m-%d")).split()[2:3])for i in df["data"]]
ax1.set_xlabel(u"Month")
ax1.set_ylabel(u"TEM(℃)")
ax2.set_ylabel("RHU(%)")
min_tem_val = min(month_min)
max_rhu_val = max(month_rhu)
ax1.set_ylim(min_tem_val - 5, 50)
ax2.set_ylim(-100, max_rhu_val + 10)
_xtick_labels = ["{}".format(i) for i in range(1, 13)]
plt.xticks(months, _xtick_labels)
# plt.title("溫濕度表")
for a, b in zip(months, month_min):
ax1.text(a, b, "%.1f" % b, ha='center', va='bottom', fontsize=8)
for a, b in zip(months, month_max):
ax1.text(a, b, "%.1f" % b, ha='center', va='bottom', fontsize=8)
for a, b in zip(months, month_avg):
ax1.text(a, b, "%.1f" % b, ha='center', va='bottom', fontsize=8)
for a, b in zip(months, month_rhu):
ax2.text(a, b, "%.1f" % b, ha='center', va='bottom', fontsize=8)
handles1, labels1 = ax1.get_legend_handles_labels()
handles2, labels2 = ax2.get_legend_handles_labels()
plt.legend(handles1 + handles2, labels1 + labels2, loc='lower center')
plt.title('%d-TEM-RHU-Table' % city_id)
plt.grid()
plt.show()
fig.savefig(os.path.join(root_path, 'image', str(city_id) + '_' + city_name + '.png'), bbox_inches='tight')
# writer = pd.ExcelWriter(os.path.join(root_path, 'ShanDong.xlsx'))
day_data.to_excel(writer, str(city_id) + city_name)
manth_data.to_excel(writer, str(city_id) + city_name, startcol=9)
四、測試結果
用山東省六個城市的數(shù)據(jù)做測試艺沼。
city_id_dict = {54725: '惠民', 54776: '成山頭', 54823: '濟南', 54843: '濰坊', 54909: '定陶', 54916: '兗州'}
writer = pd.ExcelWriter(os.path.join(root_path, 'ShanDong.xlsx'))
for city_id, city_name in tqdm(city_id_dict.items()):
main(city_id, city_name, writer)
writer.save()
輸出結果:
五册舞、總結
終于可以不用再復制粘貼的整理全國各地的溫濕度數(shù)據(jù)了,而且將自己學的東西應用到日常工作中障般,提高工作效率是多么么么么么爽快的一件事啊调鲸。
仍未解決的問題:
1.生成的溫濕度圖,不能自動插入到相應excle對應的表格里挽荡。(不能再excle中追加插入圖片)
2.沒有解決生成圖片中文出現(xiàn)編碼錯誤藐石。
3.數(shù)據(jù)處理不夠簡化,應該有很大的提升空間定拟。
在代碼過程中遇到的問題(找到相應解決方案):
數(shù)據(jù)讀取與處理
1.如何遍歷文件夾內文件于微?
2.怎樣讀取數(shù)據(jù)
3.怎樣將不同文件的數(shù)據(jù)拼接
拼接時需要忽視行索引,
4.怎樣將不同文件的數(shù)據(jù)融合
5.怎樣設置dataframe的列標題
6.將讀入的數(shù)據(jù)分為不同的列的方法
7.如何防止第一行數(shù)據(jù)當作列標題行
8.時間戳办素、時間元組角雷、時間字符串的概念及相互轉換
9.顯示進度條的工具使用方法
圖像繪制
1.如何設置橫坐標
2.如何設置兩個縱坐標
3.如何顯示曲線中關鍵點數(shù)據(jù)值