python批量计算多站点多年标准化降水指数SPI
前面提过如何计算单站点多年的标准化降水指数SPI,但是在现实中不仅只计算一个站点的标准化降水指数,有时要计算多个站点的。
原始数据是11个站点1961年至2022年每个月的降水值:
编程思路是:
1、先需要进行站点分类:
此处的难点在于需要写个for循环,根据站点名称遍历数据
for i in nameList: # 进行站点遍历 dfName = df[df['name'] == i]
2、分类后的站点,提取出rain值
此处需要将循环后的站点值根据rain提取出来关键语法是
rain = dfName.rain.values
3、利用提取后的rain值进行SPI指数的计算
# 计算标准化降水指数SPI SPI1 = gma.climet.SPI(rain) SPI3 = gma.climet.SPI(rain,Scale = 3) SPI5 = gma.climet.SPI(rain,Scale = 5) # 创建一个新DataFrame放入分类好后的站点数据 df2 = pd.DataFrame(dfName) # 把计算好的SPI值放入df2新增第一列、第二列、第三列 df2.insert(loc=0,column='SPI1',value=SPI1) df2.insert(loc=1,column='SPI3',value=SPI3) df2.insert(loc=2, column='SPI5', value=SPI5) # print(df2)
4、将算好后的SPI写入到excel中
此处简直是我的大难题,因为按站点算出来的结果,直接写入excel采用如下方法,
只会得到最后一个站点的结果,之前的站点的结果都被覆盖了,此种方法是错误的
df2.to_excel('G:/drought/processdata/lianxi/鄂尔多斯SPI.xlsx')
正确方法是:
(1)初始化一个列表
(2)在for循环里边每次产生的dataframe df2,要open的进去,然后在外边循环。
(3)把dataframe的列表temp=[]给合并起来,采用pd.concat(),把这个装满了,生成一个最终的RDF
(4)把RDF写入excel,就都拼起来完整了。
temp=[] for i in xxx: temp.append(df2) rdf=pd.concat(temp,axis=0) rdf.to_excel('res.xlsx')
完整代码如下:
#!usr/bin/env python # -*- coding:utf-8 -*- """ @author: Su @file: get_staion_id.py @time: 2023/07/26 @desc: """ import pandas as pd import gma # 打开excel文件 df = pd.read_excel('processdata/lianxi/鄂尔多斯.xlsx') # 初始化空列表为了把spi数据写入excel,避免excel总是仅得出最后一个数的情况 temp = [] # 给站点分类 nameList = set(df.name.values) # 先写个循环进行站点分类,再提取rain值进行SPI计算 for i in nameList: # 进行站点遍历 dfName = df[df['name'] == i] #df2 = pd.DataFrame() # 提取rain值 rain = dfName.rain.values # 计算标准化降水指数SPI SPI1 = gma.climet.SPI(rain) SPI3 = gma.climet.SPI(rain,Scale = 3) SPI5 = gma.climet.SPI(rain,Scale = 5) # 创建一个新DataFrame放入分类好后的站点数据 df2 = pd.DataFrame(dfName) # 把计算好的SPI值放入df2新增第一列、第二列、第三列 df2.insert(loc=0,column='SPI1',value=SPI1) df2.insert(loc=1,column='SPI3',value=SPI3) df2.insert(loc=2, column='SPI5', value=SPI5) # print(df2) # 将循环出来的结果,按站点名字一个一个的写入excel temp.append(df2) # 整合DataFrame列表里的数据,进行纵向拼接 rdf = pd.concat(temp,axis=0) # print(rdf) rdf.to_excel('processdata/lianxi/鄂尔多斯SPI.xlsx')