使用lapply或ifelse计算风向,根据风的U和V分量。

6

由于罗盘方向范围从0到360度,因此对标量风向数据进行平均会产生不准确的值,所以我已经将我的列表从大小和风向角转换为u和v分量。

为了获得正确的风向,以便进行平均,我需要为以下3种情况开发某种应用、ifelse函数:

V > 0...((180 / pi) * atan((Ucomp/Vcomp)) + 180)
U and V < 0...((180 / pi) * atan((Ucomp/Vcomp)) + 0)
U > 0 and V < 0...((180 / pi) * atan((Ucomp/Vcomp)) + 360)

在我要分析的数据集中,Ucomp大于0且Vcomp小于零,但无疑会有所有3个情况都会出现的情况,因此我需要一个函数来逐步解析和计算,并在每个时间步骤应用正确的公式。我以前没有使用过lapply或函数,因此我尝试使用它们没有成功。
我提供以下数据样本...
  DateTime Wind.Spd Wind.Direction Air.Density   Temp.C GEP.GE16XLE GCF.GE16XLE    Ucomp      Vcomp
1     1981 7.662370       248.3395   0.9148207 11.28967    597.7513    37.35946 5.253453 -0.7404972
2     1982 8.199412       251.6763   0.9172176 10.12751    678.8595    42.42872 5.867979 -0.6191475
3     1983 8.188782       251.7889   0.9162767 10.30619    667.9461    41.74663 5.777208 -1.0473982
4     1984 7.942632       246.7908   0.9174074 10.05093    642.6374    40.16484 5.415773 -0.6796723
5     1985 8.016558       252.7305   0.9171721 10.38414    654.2588    40.89117 5.649406 -0.9999082
6     1986 7.739984       249.6431   0.9158740 10.99859    607.0542    37.94089 5.305971 -0.9118965
4个回答

8

你应该考虑使用atan2函数,它可能会消除所有if语句和额外计算的需要。

如果你需要大量处理方向,那么你还应该研究circularCircStats包,它们可以为你处理很多细节(有些类似于你所做的,只是更自动化)。


我发现CircStats比另一个更好。 - John

7

请查看:

https://www.eol.ucar.edu/content/wind-direction-quick-reference

简而言之,您需要使用atan2来处理不同象限,但不要忘记气象学中角度的定义方式与其他行业不同!我们按顺时针方向以度数测量风向,而atan2类型函数通常按照从X轴(即东)开始的弧度计算。因此,您需要使用类似以下代码:

WDIR= 270-atan2(V,U)*180/pi

添加%360以确保输出在0到360之间:

WDIR= (270-atan2(V,U)*180/pi)%360


百分号是指模运算吗? - Andy Clifton
在大多数atan2函数中,应该是相反的:atan2(u,v)而不是atan2(v,u)。但它并不一致,所以首先检查很重要。 - Whir

7

首先定义一个函数来进行计算:

windDir <- function(u, v) {
  if(v > 0)         ((180 / pi) * atan(u/v) + 180)
  if(u < 0 & v < 0) ((180 / pi) * atan(u/v) + 0)
  if(u > 0 & v < 0) ((180 / pi) * atan(u/v) + 360)
}

然后将它应用于每一行。这里我使用 ddply,它是数据框的一种很好的“应用”方式:

> library(plyr)
> ddply(data, 'DateTime', summarize, windDir=windDir(Ucomp, Vcomp))
  DateTime  windDir
1     1981 278.0232
2     1982 276.0232
3     1983 280.2760
4     1984 277.1531
5     1985 280.0370
6     1986 279.7517

1
非常好,谢谢John,完美地解决了问题。我在阅读其他论坛时看到了plyr包,但尝试坚持使用适用于标量的aggregate函数,但对于这个问题,我需要其他东西。我还在摆弄一些复杂的if else语句,但是我无法完全理解它。感谢您的帮助。 - RWJ
我只对每月平均数据和跨越30年的年度平均数据进行处理,所以它对我的目的来说很有效。 - RWJ
参考Greg Snow的评论:即使不使用atan2,通常也可以通过逻辑运算节省大量时间和计算。例如,对于任意函数f,g,可以使用以下公式y<- f(x)*sign(x) + (x==0) * g(x)。x < 0 ,x = 0,x > 0时y的值留给读者自行思考 :-) - Carl Witthoft
嗨,我正在尝试使用winDir函数,但我得到了这个输出:Error in if (u < 0 & v < 0) { : missing value where TRUE/FALSE needed。我的数据框中有一些NA,所以我添加了以下行但没有成功 uNA<-is.na(u) vNA<-is.na(v) if(uNA=T) ("NA") if(vNA=T) ("NA")。任何提示将不胜感激,Rafael。 - Rafael

4
windDir <- function(u, v) {
  (180 / pi) * atan(u/v) + ifelse(v>0,180,ifelse(u>0,360,0))
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接