Tips:
本期向大家分享SwatWeather使用和天气发生器构建方法。如果上一期的气象数据都是完整的,没有缺失值和异常值,那么就不需要使用SwatWeather和天气发生器。需要注意的是,输入SwatWeather中的异常值不需要替换为-99,读取的数据也不需要进行单位转换,其量纲与原始气象数据相同,这与上一期气象数据库的制备不同。此外,SwatWeather每次只能读取一个站点的气象数据,共有22个站点,5项气象数据,所以需要操作该软件110次,目前我没有发现有其他更高效的办法。
1 SwatWeather使用方法
1.1 SwatWeather简介
SwatWeather界面如下,是一个长条状,有5项气象数据的参数计算功能区。输入的数据格式必须是txt文件格式,且有严格的表头格式要求,各项数据必须按下图顺序排列。
1.2 Python批量转换原始气象数据为SwatWeather可读格式
①原始气象数据说明
原始气象数据表共有12个字段:站号、年份、月份、日、平均风速、日照时数、平均气温、日最高气温、日最低气温、平均水气压、平均相对湿度、20-20降水量。
②代码:批量转换原始气象数据为SwatWeather可读格式
由于我的原始气象观测数据没有蒸散发的数据,所以直接用-99代替。但是要注意,其他列的数据异常值不要改成-99,因为SwatWeather会自动识别异常值修改为-99。
import os
import pandas as pd
# 定义文件夹路径
folder_path = r'C:\你的路径\存放Excel格式原始气象数据的文件夹'
# 获取文件夹中所有Excel文件的路径
excel_files = [os.path.join(folder_path, f) for f in os.listdir(folder_path) if f.endswith('.xlsx')]
# 遍历每个Excel文件
for excel_file in excel_files:
# 获取当前Excel文件的名称
excel_filename = os.path.basename(excel_file)
# 拿到代码之后需要按照自己气象数据修改的部分======================================================================
# 截取前6个字符,假设格式是"[56018]杂多.xlsx",取出 "56018"
file_prefix = excel_filename[1:6] # 修改索引以适应实际情况
# 气象数据的起始日期
start_date = '20050101'
# 定义p数据的输出文件名,加上后缀 "pcp、tem、w、h"
station_output = f"{file_prefix}.txt"
# 读取Excel文件中的第一个工作表
df = pd.read_excel(excel_file, sheet_name=0) # sheet_name=0 表示第一个工作表
# 筛选出2014年往后的数据
for index,time in enumerate(df['年']):
if time==int(start_date[:4]): # start_date[:4]表示年份
start=index #找到2014年的索引,后续读取从2014年开始往后的数据
break
pcp=list(df['20-20降水量'][start:])
temmax=list(df['日最高气温'][start:])
temmin=list(df['日最低气温'][start:])
temavg=list(df['平均气温'][start:])
w=list(df['平均风速'][start:])
h=list(df['平均相对湿度'][start:]) # 除以100,将百分比转换为小数
e=list(df['平均水汽压'][start:])
# 概化气压,有总比没有强
p=[round(i/j*100,2) for i, j in zip(e, h)] #利用水汽压与相对湿度概化气压,并保留两位小数
sd = list(df['日照时数'][start:])
year=list(df['年'][start:])
month=list(df['月'][start:])
day=list(df['日'][start:])
with open(station_output, 'w', encoding='utf-8') as file:
for i in range(len(pcp)):# 顺序:站点号、年、月、日、平均气压、平均风速、平均气温、最高气温、最低气温、相对湿度、降水、小型蒸发、大型蒸发、日照时数
file.write(f"{file_prefix}\t{int(year[i])}\t{int(month[i])}\t{int(day[i])}\t"
f"{p[i]}\t{int(w[i])}\t{int(temavg[i])}\t{int(temmax[i])}\t{int(temmin[i])}\t"
f"{int(h[i])}\t{int(pcp[i])}\t{-99}\t{-99}\t{int(sd[i])}\t\n")
③代码运行结果
成功生成SwatWeather可读的txt格式气象文件,任意打开一个txt文件发现各列顺序是正确的。22个站点,所以共生成22个txt气象数据文件,这比手动制备节省了大量时间。
1.3 SwatWeather操作步骤
①计算降水
打开代码生成的txt气象数据文件,检查日期和降水格式正确。按顺序点击剩余4个按钮“设置计算目录”——“生成计算文件”——“计算”——“生成降水”。
在设置的计算目录中找到“pcpresult.txt”,能够看到按月计算出来的各种降水参数。
新建Excel表,将计算结果复制粘贴到表里,在粘贴选项选择“使用文本导入向导”,然后转置。
②计算气温
打开代码生成的txt气象数据文件,检查日期和气温格式正确。按顺序点击剩余3个按钮“计算最高”——“计算最低”——“生成气温”。计算最高时命名输出结果为tmax,计算最低时命名输出结果为tmin,这样方便记。
分别打开tmax和tmin,倒数第二项是计算的月平均结果,倒数第一项是标准差,我们只用得到前者。
将计算结果复制粘贴到表里,在粘贴选项选择“使用文本导入向导”。
计算气温思路参考:
③计算辐射
输入站点纬度,打开代码生成的txt气象数据文件,检查日期、气温和日照时数格式正确。按顺序点击剩余3个按钮“生成天数”——“计算分项”——“统计计算”。统计计算命名输出结果为SOLresult,这样方便记。
在点击“计算分项”后,有可能会出现计算结果非数字的情况,如下图所示,这因为SwatWeather自身的问题,它并不能计算所有纬度的太阳辐射,要解决这个问题,就要对纬度进行微调,将纬度值增大一点或减小一点,再重新计算分项。
打开SOLresult,最后一项是计算的月平均结果。
将计算结果复制粘贴到表里,在粘贴选项选择“使用文本导入向导”。
④计算风速
输入站点纬度,打开代码生成的txt气象数据文件,检查日期和风速格式正确。按顺序点击剩余2个按钮“计算各年”——“生成风速”。计算各年命名输出结果为Wresult,这样方便记。
打开Wresult,最后一项是计算的月平均结果。
将计算结果复制粘贴到表里,在粘贴选项选择“使用文本导入向导”。
⑤计算露点
打开代码生成的txt气象数据文件,检查日期、气温和相对湿度格式正确。按顺序点击剩余4个按钮“设置计算目录”——“生成计算文件”——“计算”——“生成相对湿度CSV”。
在设置的计算目录中找到“dewresult.txt”,能够看到按月计算出来的露点相关参数。
将计算结果复制粘贴到表里,在粘贴选项选择“使用文本导入向导”,然后转置。
1.4 结果处理
由于数据最多保留两位小数,所以将汇总好的数据保留两位小数,并非是数据格式的显示两位小数,而是将结果只剩下两位小数,其余的删除。可以使用round函数实现,在excel中,round函数是专用于数字的四舍五入转换,输入公式为:=ROUND(某单元格,2)。
注意截至目前,我们处理的都是一个站点的数据,共有22个站点,要重复上述操作22次。
2 天气发生器数据库制作
找到ArcSWAT自带的参数据,一个SWAT工程包含3个数据库,分别是:工程库(工程名.mdb)、栅格库(RasterStore.mdb)、参数库(SWAT2012.mdb)。在参数库中找到WGEN_user表,参数库的默认路径是:
电脑下载ArcSWAT的路径\ArcSwat\Databases\SWAT2012.mdb
复制一份参数库(SWAT2012.mdb),将WGEN_user表中的内容删除,将SwatWeather得到的结果根据列名复制到WGEN_user表的对应位置。复制粘贴完成后,会发现WGEN_user中的12个RAINHHMX列还是空白的,这个参数是月最大半小时降水量,SwatWeather无法计算该参数,网上一些老师和博主推荐的方法是:在CFSR世界气象数据库中找到相近经纬度对应的RAINHHMX值来代替。
CFSR下载网址:
SwatWeather得到的一个站点的结果对应WGEN_user的一行数据,共有22个站点,所以最后WGEN_user表中应有22行数据,天气发生器的数据库制作完成。数据最多保留两位小数。
以上是全部内容,欢迎大家评论区留言,批评指正