python批量计算多站点多年标准化降水指数SPI

发布时间 2023-07-26 16:04:21作者: 蓝色大螃蟹

前面提过如何计算单站点多年的标准化降水指数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('G:/drought/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('G:/drought/processdata/lianxi/鄂尔多斯SPI.xlsx')