爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 13687|回复: 3

[经验总结] 利用python处理气象数据

[复制链接]

新浪微博达人勋

发表于 2020-12-15 21:53:03 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
python小白初初面对气象数据处理,遇到了以下需求:
1.要将不同月份的数据分开,取显热通量H与潜热通量LH该月的每小时平均值;
2.wrf模拟结果要加八小时才能与观测值对上;
3.模拟数据有俩,分别为txt文件“test1.TXT”、“test2.TXT”;观测值为excel文件“testdata.xlsx”。要把不同类型的文件写入,画在同一张图上。

不知各位大神有木有更好的方法来解决这些问题~
代码如下:
import pandas as pd
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import os
from datetime import timedelta
# mon:月份
# data:对应的数据
# 将数据data写入到对应的mon模拟文件当中,文件命名为SIM9.txt
def toFile_SIM(mon, data,fangan):
    path = "SIM"+fangan+"-" + str(mon) +'.txt'
    s = ""
    if JudgeFile(path):
        pass
    else:
        s = s + "Time H FCEV FGEV FCTR T \n"
        print("第一次创建")

    for i in data:
        s = s + str(i) + "    "
    with open(path, 'a')as f:
        f.write(s + '\n')

# mon:月份
# data:对应的数据
# 将数据data写入到对应的mon实测文件当中,文件命名为OBS9.txt
def toFile_OBS(mon, data):
    path = "OBS" + str(mon) + '.txt'
    s = ""
    if JudgeFile(path):
        pass
    else:
        s = s + "Time H LH\n"
        print("第一次创建")

    for i in data:
        s = s + str(i) + "    "
    with open(path, 'a')as f:
        f.write(s + '\n')

#方案1
#把模拟数据的dataframe 根据月份进行分发到文件当中
def DeliverToFile_SIM_1(df1):
    for i in range(len(df1['Time'])):
        df1['Time'] = pd.to_datetime(str(df1['Time']))
        df1['Time'] = df1['Time'] + timedelta(hours=8)
    t1 = np.array(df1['Time'])
    for i in range(len(t1)):
        mon = int(str(t1.date())[5:7])
        toFile_SIM(mon, df1.iloc.tolist(),"1")

#方案2
#把模拟数据的dataframe 根据月份进行分发到文件当中
def DeliverToFile_SIM_2(df1):
    for i in range(len(df1['Time'])):
        df1['Time'] = pd.to_datetime(str(df1['Time']))
        df1['Time'] = df1['Time'] + timedelta(hours=8)
    t1 = np.array(df1['Time'])
    for i in range(len(t1)):
        mon = int(str(t1.date())[5:7])
        toFile_SIM(mon, df1.iloc.tolist(),"2")#把实测数据的dataframe 根据月份进行分发到文件当中
def DeliverToFile_OBS(df1):
    for i in range(len(df1['Time'])):
        df1['Time'] = pd.to_datetime(str(df1['Time']))
    t1 = np.array(df1['Time'])
    for i in range(len(t1)):
        mon = int(str(t1.date())[5:7])
        toFile_OBS(mon, df1.iloc.tolist())


# 传入一个DataFrame,返回一个数组arrarr表示在该DataFrame中,第i个小时的平均值
# 用于计算H的模拟值
def calMonAver_H_SIM(df):
    for i in range(len(df['Time'])):
        df['Time'] = pd.to_datetime(str(df['Time']))
    t = np.array(df['Time'])
    H = np.array(df['H'])
    arr = [0] * 25  # arr 代表第i个小时的总和
    count = [0] * 25  # 表示数量
    for i in range(len(t)):
        arr[int(str(t.time())[0:2])] = arr[int(str(t.time())[0:2])] + H
        count[int(str(t.time())[0:2])] = count[int(str(t.time())[0:2])] + 1

    for i in range(len(arr) - 1):
        arr = arr / count
    return arr

# 传入一个DataFrame,返回一个数组arrarr表示在该DataFrame中,第i个小时的平均值
# 用于计算LH的模拟值
def calMonAver_LH_SIM(df):
    for i in range(len(df['Time'])):
        df['Time'] = pd.to_datetime(str(df['Time']))
    t = np.array(df['Time'])
    LH = np.array(df['FCEV']+df['FGEV']+df['FCTR'])
    arr = [0] * 25  # arr 代表第i个小时的总和
    count = [0] * 25  # 表示数量
    for i in range(len(t)):
        arr[int(str(t.time())[0:2])] = arr[int(str(t.time())[0:2])] + LH
        count[int(str(t.time())[0:2])] = count[int(str(t.time())[0:2])] + 1

    for i in range(len(arr) - 1):
        arr = arr / count
    return arr

# 传入一个DataFrame,返回一个数组arrarr表示在该DataFrame中,第i个小时的平均值
# 用于计算LH的实测值
def calMonAver_LH_OBS(df):
    t = np.array(df['Time'])
    LE = np.array(df['LH'])
    arr = [0] * 25  # arr 代表第i个小时的总和
    count = [0] * 25  # 表示数量
    for i in range(len(t)):
        data = LE
        if str(LE) == 'nan':
            data = 0
        arr[int(str(t)[0:2])] = arr[int(str(t)[0:2])] + data
        if data != 0:
            count[int(str(t)[0:2])] = count[int(str(t)[0:2])] + 1

    for i in range(len(arr) - 1):
        arr = arr / count
    return arr

# 传入一个DataFrame,返回一个数组arrarr表示在该DataFrame中,第i个小时的平均值
# 用于计算H的实测值
def calMonAver_H_OBS(df):
    t = np.array(df['Time'])
    H = np.array(df['H'])
    arr = [0] * 25  # arr 代表第i个小时的总和
    count = [0] * 25  # 表示数量
    for i in range(len(t)):
        data = H
        if str(H) == 'nan':
            data = 0
        arr[int(str(t)[0:2])] = arr[int(str(t)[0:2])] + data
        if data != 0:
            count[int(str(t)[0:2])] = count[int(str(t)[0:2])] + 1

    for i in range(len(arr) - 1):
        arr = arr / count
    return arr

# path:需要处理的excel文件的路径
# 用于对实测数据的excel进行规范化处理,返回dataframe
# 最终的dataframe只包括:Time,H,LE三列
def FormatExcel(path):
    df = pd.read_excel(path)
    date = df['date']
    time =df['time']
    Time = []
    for i in range(len(date)):
        Time.append(str(date) + str(time))
        Time = Time.replace(' 00:00:00',' ')
    mydic = {'Time':Time,'H':df['H'].tolist(),'LE':df['LH'].tolist()}
    df = pd.DataFrame(mydic)
    return df


"""
    使用步骤:
        1.模拟数使用d据:
            a.f = pd.read_csv()读取待处理的模拟数据的txt文件,得到df
            b.调用DeliverToFile_SIM(df)将模拟文件的数据按照月份进行分发,得到若干个SIMx.txt文件 (x表示月份)
            c.再根据上一个步骤生成了的txt文件,调用 dfx = pd.read_csv("SIMx.txt")方法获取对应月份的dfx
            d.调用arr1 = calMonAver_H_SIM(dfx)arr2 = calMonAver_LH_SIM(dfx)生成两个数组,调用plot(arr1);plot(arr2)的方法生成折线图
        2.实测数据:
            a.使用df = FormatExcel("DHSdata.xlsx")读取待处理的实测数据的txt文件,得到df
            b.DeliverToFile_OBS(df)将实测文件的数据按照月份进行分发,得到若干个OBSx.txt文件 (x表示月份)
            c.再根据上一个步骤生成了的txt文件,调用 dfx = pd.read_csv("OBSx.txt")方法获取对应月份的dfx
            d.调用arr1 = calMonAver_H_OBS(dfx)arr2 = calMonAver_LH_OBS(dfx)生成两个数组,调用plot(arr1);plot(arr2)的方法生成折线图
            
"""

df1 = pd.read_csv("testg1.TXT",sep='\s+')
DeliverToFile_SIM_1(df1)
#
#
df2 = pd.read_csv("testg5.TXT",sep='\s+')
DeliverToFile_SIM_2(df2)
#
df3 = FormatExcel("testdata.xlsx")
DeliverToFile_OBS(df3)

df1 = pd.read_csv("SIM1-8.txt",sep='\s+')
df2 = pd.read_csv("SIM2-8.txt",sep='\s+')
df3 = pd.read_csv("OBS8.txt",sep='\s+')

arr1_1 = calMonAver_H_SIM(df1)
arr1_2 = calMonAver_LH_SIM(df1)

arr2_1 = calMonAver_H_SIM(df2)
arr2_2 = calMonAver_LH_SIM(df2)

arr3_1 = calMonAver_H_OBS(df3)
arr3_2 = calMonAver_LH_OBS(df3)

x = range(25)

plt.plot(x,arr1_1,label='case1-H')
plt.plot(x,arr1_2,label='case1-LH')
plt.plot(x,arr2_1,label='case2-H')
plt.plot(x,arr2_2,label='case2-LH')
plt.scatter(x,arr3_1,label='obs-H')
plt.scatter(x,arr3_2,label='obs-LH')
plt.xlabel('time')
plt.ylabel('Heat Flux')
plt.title('August')
plt.legend()
plt.savefig("8.1-res.png")
plt.show()

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2020-12-16 08:32:47 | 显示全部楼层
本帖最后由 edwardli 于 2020-12-16 14:22 编辑

我感觉你描述的需求,除去图形属性之类的,核心实现最多也就40行代码就OK。
比如求平均值,dataframe的mean就可以计算平均值,还可以把nan值忽略ignore;
再比如按月份或者按小时,分类汇总也是dataframe的基本功能。
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

 楼主| 发表于 2020-12-16 19:39:48 | 显示全部楼层
edwardli 发表于 2020-12-16 08:32
我感觉你描述的需求,除去图形属性之类的,核心实现最多也就40行代码就OK。
比如求平均值,dataframe的mea ...

谢谢大佬指点!!!
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

新浪微博达人勋

发表于 2020-12-22 08:35:52 | 显示全部楼层
{:eb502:}{:eb502:}{:eb502:}
密码修改失败请联系微信:mofangbao
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表