【问题标题】:Calculating wind direction from U and V components of the wind using lapply or ifelse使用 lapply 或 ifelse 从风的 U 和 V 分量计算风向
【发布时间】:2025-11-30 14:10:01
【问题描述】:

平均标量风向数据会产生不准确的值,因为指南针的航向范围为 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

【问题讨论】:

    标签: r


    【解决方案1】:

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

    如果您在方向上做了很多工作,那么您还应该查看 circularCircStats 包,它们会为您处理很多这些细节(有些类似于您所做的,只是更自动) .

    【讨论】:

    • 我发现 CircStats 是两者中的佼佼者。
    【解决方案2】:

    首先定义函数进行计算:

    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
    

    【讨论】:

    • 美丽...谢谢约翰...完美。我在阅读其他论坛时看到了 plyr 包,但尝试坚持使用与标量配合良好的聚合,但对于这个问题,我需要别的东西。我还在胡闹一些我不太明白的 if else 语句。感谢您的帮助
    • 我只对 30 年的月平均数据和年平均数据进行分析,所以它适用于我的目的。
    • 见 Greg Snow 的评论:即使不使用atan2,通常也可以通过逻辑运算节省大量时间和计算。例如。对于任意函数 f,g y&lt;- f(x)*sign(x) + (x==0) * g(x) 。 x 0 的 y 的值留给读者作为练习:-)
    • 嗨,我正在尝试使用 winDir 函数,但我得到了以下输出:Error in if (u &lt; 0 &amp; v &lt; 0) { : missing value where TRUE/FALSE needed。我的数据框中有一些 NA,所以我添加了以下行但没有成功uNA&lt;-is.na(u) vNA&lt;-is.na(v) if(uNA=T) ("NA") if(vNA=T) ("NA")。任何提示将不胜感激,拉斐尔
    【解决方案3】:

    退房:

    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

    【讨论】:

    • % 应该是模数吗?
    • 在大多数 atan2 函数中,它应该相反:atan2(u,v) 而不是 atan2(v,u)。但它并不一致,因此首先检查这一点很重要。
    【解决方案4】:
    windDir <- function(u, v) {
      (180 / pi) * atan(u/v) + ifelse(v>0,180,ifelse(u>0,360,0))
    }
    

    【讨论】: