天天看點

Python資料分析實戰:降雨量統計分析報告分析

本文的文字及圖檔來源于網絡,僅供學習、交流使用,不具有任何商業用途,如有問題請及時聯系我們以作處理。

以下文章來源于菜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 %}      

即:

Python資料分析實戰:降雨量統計分析報告分析

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")