前面提过如何计算单站点多年的标准化降水指数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')