python - 使用 Pandas Dataframe 对可变时间段的天气数据进行重采样
问题描述
我一直在尝试创建一个通用的天气导入器,它可以重新采样数据以设置间隔(例如从 20 分钟到几小时等(我在下面的代码中使用了 60 分钟))。为此,我想使用 Pandas 重采样功能。经过一番困惑后,我想出了下面的代码(这不是最漂亮的代码)。我在设定时间段内平均风向时遇到了一个问题,我试图用 pandas 的 resampler.apply 来解决这个问题。
但是,我遇到了一个定义问题,它给出了以下错误:TypeError: can't convert complex to float
我意识到我正在尝试在圆孔中强制使用方形钉,但我不知道如何克服这一点。任何提示将不胜感激。
import pandas as pd
import os
from datetime import datetime
from pandas import ExcelWriter
from math import *
os.chdir('C:\\test')
file = 'bom.csv'
df = pd.read_csv(file,skiprows=0, low_memory=False)
#custom dataframe reampler (.resampler.apply)
def custom_resampler(thetalist):
try:
s=0
c=0
n=0.0
for theta in thetalist:
s=s+sin(radians(theta))
c=c+cos(radians(theta))
n+=1
s=s/n
c=c/n
eps=(1-(s**2+c**2))**0.5
sigma=asin(eps)*(1+(2.0/3.0**0.5-1)*eps**3)
except ZeroDivisionError:
sigma=0
return degrees(sigma)
# create time index and format dataframes
df['DateTime'] = pd.to_datetime(df['DateTime'],format='%d/%m/%Y %H:%M')
df.index = df['DateTime']
df = df.drop(['Year','Month', 'Date', 'Hour', 'Minutes','DateTime'], axis=1)
dfws = df
dfwdd = df
dfws = dfws.drop(['WDD'], axis=1)
dfwdd = dfwdd.drop(['WS'], axis=1)
#resample data to xxmin and merge data
dfwdd = dfwdd.resample('60T').apply(custom_resampler)
dfws = dfws.resample('60T').mean()
dfoutput = pd.merge(dfws, dfwdd, right_index=True, left_index=True)
# write series to Excel
writer = pd.ExcelWriter('bom_out.xlsx', engine='openpyxl')
dfoutput.to_excel(writer, sheet_name='bom_out')
writer.save()
解决方案
做了更多的研究,发现改变定义效果最好。然而,这通过相反的角度(180 度)划分给出了一个奇怪的结果,这是我偶然发现的。我不得不扣除一个小值,这会在实际结果中产生度数误差。
我仍然有兴趣知道:
- 复杂的数学做错了什么
- 对角的更好解决方案(180 度)
# changed the imports
from math import sin,cos,atan2,pi
import numpy as np
#changed the definition
def custom_resampler(angles,weights=0,setting='degrees'):
'''computes the mean angle'''
if weights==0:
weights=np.ones(len(angles))
sumsin=0
sumcos=0
if setting=='degrees':
angles=np.array(angles)*pi/180
for i in range(len(angles)):
sumsin+=weights[i]/sum(weights)*sin(angles[i])
sumcos+=weights[i]/sum(weights)*cos(angles[i])
average=atan2(sumsin,sumcos)
if setting=='degrees':
average=average*180/pi
if average == 180 or average == -180: #added since 290 degrees and 110degrees average gave a weird outcome
average -= 0.1
elif average < 0:
average += 360
return round(average,1)
推荐阅读
- java - 使用 Spring 为 RabbitMQ 配置创建 SSLContext
- windows - Windows 任务计划程序作业每两分钟
- c# - 第二次使用同一张卡时自适应卡id冲突
- actionscript-3 - as3 adobe animate中的打印按钮
- c - 当服务器关闭连接并且客户端同时发送一些数据时会发生什么?
- maven - 从 Azure DevOps 发布声纳扫描结果
- sql - 如何仅选择一列对于同一 ID 可以具有空值或非空值的行
- flutter - “ControllerMVC*”类型的值不能分配给“DeliveryAddressesController?”类型的变量
- sql - SQL SSRS 从报告中打开 Docx 文件
- json - 如何在json文件中使用if else条件