本文的文字及圖檔來源于網絡,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理。
以下文章來源于菜J學Python ,作者小小明
最近遇到一個有點燒腦的需求,其實也不算燒腦,主要是判斷條件過多,對于我這種記憶力差,記憶體小的人來說容易出現記憶體溢出導緻大腦當機。也可能是因為我還沒有找到能減小大腦記憶體壓力的方法。
先看看需求吧:
主要就是要根據左側的表格自動生成右側的Word統計報告,實際的各種可能性情況遠比圖中展示的要更加複雜。
好了,直接開始幹代碼吧!
1資料讀取
import pandas as pd
df = pd.read_csv("11月份資料.csv", encoding='gbk')# 目前統計月份month = 11df = df.query('月份==@month')
df.head(10)
預覽資料:
2異常資料過濾
檢視缺失值數量:
pd.isnull(df).sum()
結果:
區域 0
月份 0
降雨量(mm) 0
降雨距平(mm) 1觀測站 0
dtype: int64
僅一個缺失值資料,可直接删除:
df.dropna(inplace=True)
3計算觀測站降雨量相對往年的變化
計算降雨量比往年高,跟往年比無變化,以及比往年低的次數分别是多少:
rainfall_high = df.eval('`降雨距平(mm)` > 0').value_counts().get(True, 0)
rainfall_equal = df.eval('`降雨距平(mm)` == 0').value_counts().get(True, 0)
rainfall_low = df.eval('`降雨距平(mm)` < 0').value_counts().get(True, 0)print(rainfall_high, rainfall_equal, rainfall_low)13 1 18
上面的結果中rainfall_high表示降雨量比往年平均水準高的次數,rainfall_equal表示降雨量比往年平均水準持平的次數,rainfall_low表示降雨量比往年平均水準低的次數。
于是分情況讨論生成第一段的報告:
p1 = f"{month}月份"if rainfall_low == 0 or rainfall_high == 0:if rainfall_equal != 0:
p1 += f"除{rainfall_equal}個觀測站降雨量較往年無變化外,"if rainfall_high == 0:
p1 += f"各氣象觀測站降雨量較往年均偏低。"elif rainfall_low == 0:
p1 += f"各氣象觀測站降雨量較往年均偏高。"else:# 10%以内差異認為是持平if rainfall_high > rainfall_low*1.1:
p1 += f"大部分氣象觀測站降雨量較往年偏高。"elif rainfall_low > rainfall_high*1.1:
p1 += f"大部分氣象觀測站降雨量較往年偏低。"else:
p1 += f"各氣象觀測站降雨量較往年整體持平。"p1
'11月份大部分氣象觀測站降雨量較往年偏低。'
4計算各區域降雨量的極值
再生成第二段的報告:
p2 = ""t = df['降雨量(mm)']
p2 += f"各區域降雨量在{t.min()}~{t.max()}mm之間,其中{df.loc[t.argmax(), '區域']}區域的降雨量最大,為{t.max()}mm。"p2
'各區域降雨量在0.0~16.0mm之間,其中51a45區域的降雨量最大,為16.0mm。'
5分觀測站統計
讓我腦袋疼的地方就是從這裡的代碼開始的,後面還有更複雜的需求就不公布了。
對每個觀測站分别統計哪些區域偏高,哪些區域持平,哪些區域偏低:
p3s = []for station, tmp in df.groupby('觀測站'):
t = tmp['降雨量(mm)']
p3 = f"各區域降雨量在{t.min()}~{t.max()}mm之間,"rainfall_high_mask = tmp.eval('`降雨距平(mm)` > 0')
rainfall_equal_mask = tmp.eval('`降雨距平(mm)` == 0')
rainfall_low_mask = tmp.eval('`降雨距平(mm)` < 0')
rainfall_high = rainfall_high_mask.value_counts().get(True, 0)
rainfall_equal = rainfall_equal_mask.value_counts().get(True, 0)
rainfall_low = rainfall_low_mask.value_counts().get(True, 0)# print(rainfall_high, rainfall_equal, rainfall_low)if rainfall_low == 0 or rainfall_high == 0:if rainfall_equal != 0:
p3 += '除'p3 += '、'.join(tmp.loc[rainfall_equal_mask, '區域']+'區域')
p3 += "降雨量較往年無變化外,"if rainfall_high == 0:
p3 += f"各區域降雨量均較往年偏低"elif rainfall_low == 0:
p3 += f"各區域降雨量均較往年偏高"t = tmp['降雨距平(mm)'].abs()
p3 += f"{t.min()}~{t.max()}mm;"else:if rainfall_equal != 0:
p3 += '除'p3 += '、'.join(tmp.loc[rainfall_equal_mask, '區域']+'區域')
p3 += "降雨量較往年無變化,"# 10%以内差異認為是持平if rainfall_high > rainfall_low*1.1:if rainfall_equal == 0:
p3 += '除'p3 += '、'.join(tmp.loc[rainfall_low_mask, '區域']+'區域')
p3 += "降雨量較往年偏低"t = tmp.loc[rainfall_low_mask, '降雨距平(mm)'].abs()if t.shape[0] > 1:
p3 += f"{t.min()}~{t.max()}mm"else:
p3 += f"{t.min()}mm"p3 += "外,"t = tmp.loc[rainfall_high_mask, '降雨距平(mm)'].abs()
p3 += f"其餘各區域降雨量較往年偏高{t.min()}~{t.max()}mm;"elif rainfall_low > rainfall_high*1.1:if rainfall_equal == 0:
p3 += '除'p3 += '、'.join(tmp.loc[rainfall_high_mask, '區域']+'區域')
p3 += "降雨量較往年偏高"t = tmp.loc[rainfall_high_mask, '降雨距平(mm)'].abs()if t.shape[0] > 1:
p3 += f"{t.min()}~{t.max()}mm"else:
p3 += f"{t.min()}mm"p3 += "外,"t = tmp.loc[rainfall_low_mask, '降雨距平(mm)'].abs()
p3 += f"其餘各區域降雨量較往年偏低{t.min()}~{t.max()}mm;"else:if rainfall_equal != 0:
p3 = p3[:-1]+'外,'p3 += f"各區域降雨量較往年偏高和偏低的數量持平,其中"p3 += '、'.join(tmp.loc[rainfall_low_mask, '區域']+'區域')
p3 += "降雨量較往年偏低"t = tmp.loc[rainfall_low_mask, '降雨距平(mm)'].abs()if t.shape[0] > 1:
p3 += f"{t.min()}~{t.max()}mm,"else:
p3 += f"{t.min()}mm,"p3 += '、'.join(tmp.loc[rainfall_high_mask, '區域']+'區域')
p3 += "降雨量較往年偏高"t = tmp.loc[rainfall_high_mask, '降雨距平(mm)'].abs()if t.shape[0] > 1:
p3 += f"{t.min()}~{t.max()}mm;"else:
p3 += f"{t.min()}mm;"p3s.append([station, p3])
p3s[-1][-1] = p3s[-1][-1][:-1]+"。"p3s
可能是我還沒有想出較好的封裝方式導緻代碼變得這麼複雜,如果有巧妙解決這個問題的朋友,希望能夠加菜J學Python交流群一起探讨。
6将組織好的文本寫入到word中
Word模闆檔案docxtemplate.docx的内容:
一、{{ month }}月各氣象觀測站降雨量實況
(一)降水
{{ p1 }}
{{ p2 }}
{%p for station,p3 in p3s %}
{{ station }}:{{ p3 }}
{%p endfor %}
即:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-cmbw5yYzYDOjNTOyMGM0UWZ1I2MyUmM0EGMyYGOlZTYkNTOh9CX4AzLcFDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL1M3Lc9CX6MHc0RHaiojIsJye.png)
Python渲染代碼:
from docxtpl import DocxTemplate
tpl = DocxTemplate("docxtemplate.docx")
context = {'month': month,'p1': p1,'p2': p2,'p3s': p3s,
}
tpl.render(context)
tpl.save("11月降雨量報告.docx")