首页 > 解决方案 > 当被要求处理矢量输入与独立用户输入时,函数计算错误答案的问题

问题描述

功能概述

我创建了一个函数来计算连续方位之间的方向变化(这是根据我的纬度和经度数据计算的)。

方位角总是相对于南北线(即,远离北方的度数),因此彼此平行,并且是正的 (0 -> +180) 或负的 (0 -> -180)。我已经考虑了方位的符号(正或负)和“幅度”(>90 或 <90),这使我能够使用基本三角函数来创建“规则”来计算方向变化。

该函数评估两个连续的方位(即 A --- TO --- B),对其方向(正或负)和方位值(>90 或 <90)进行分类。它使用这些分类来确定使用哪个“规则”,然后使用与该规则关联的计算来计算方向变化。请看下面的函数:

功能

analyzeGPS_DirectionChange <- function(bearingVec1, bearingVec2) {

  a1 <- ifelse (bearingVec1 >= 0.00, "positive", "negitive")
  a2 <- ifelse (bearingVec2 >= 0.00, "positive", "negitive")
  Bearing_Signs <- paste(a1, a2)

  b1 <- ifelse (abs(bearingVec1) < 90.00, "less", "greater")
  b2 <- ifelse (abs(bearingVec2) < 90.00, "less", "greater")
  Bearing_Values <- paste(b1, b2)

  print(Bearing_Signs)
  print(Bearing_Values)

  if (Bearing_Signs == "positive positive" && Bearing_Values == "less less") {
      Direction_Change <- (90 - bearingVec1) + (90 + bearingVec2)
      } else if (Bearing_Signs == "positive positive" && Bearing_Values == "less greater") {
      Direction_Change <- (180 - bearingVec2) + bearingVec1
      } else if (Bearing_Signs == "positive positive" && Bearing_Values == "greater less") {
      Direction_Change <- 180 - ((bearingVec1 - 90) + (90 - bearingVec2))
      } else if (Bearing_Signs == "positive positive" && Bearing_Values == "greater greater") {
      Direction_Change <- (bearingVec1 - 90) + (180 - bearingVec2) + 90 
  }

  if (Bearing_Signs == "positive negitive" && Bearing_Values == "less less") {
      Direction_Change <- 180 - (abs(bearingVec2) + bearingVec1)
      } else if (Bearing_Signs == "positive negitive" && Bearing_Values == "less greater") {
      Direction_Change <- 180 - (90 + (90 - bearingVec1) + (180 - abs(bearingVec2)))
      } else if (Bearing_Signs == "positive negitive" && Bearing_Values == "greater less") {
      Direction_Change <- 90 - ((bearingVec1 - 90) + abs(bearingVec2))
      } else if (Bearing_Signs == "positive negitive" && Bearing_Values == "greater greater")  {
      Direction_Change <- 180 - ((180 - bearingVec1) + (180 - abs(bearingVec2)))
  }

  if (Bearing_Signs == "negitive positive" && Bearing_Values == "less less") {
      Direction_Change <- 180 - (abs(bearingVec1) + bearingVec2)
      } else if (Bearing_Signs == "negitive positive" && Bearing_Values == "less greater") {
      Direction_Change <- 180 - (90 + (90 - abs(bearingVec1)) + (180 - bearingVec2))
      } else if (Bearing_Signs == "negitive positive" && Bearing_Values == "greater less") {
      Direction_Change <- 90 - ((abs(bearingVec1) - 90) + bearingVec2)
      } else if (Bearing_Signs == "negitive positive" && Bearing_Values == "greater greater")  {
      Direction_Change <- 180 - ((180 - abs(bearingVec1)) + (180 - bearingVec2))
  }

  if (Bearing_Signs == "negitive negitive" && Bearing_Values == "less less") {
      Direction_Change <- (90 - abs(bearingVec2)) + (90 + abs(bearingVec1))
      } else if (Bearing_Signs == "negitive negitive" && Bearing_Values == "less greater") {
      Direction_Change <- (180 - abs(bearingVec2)) + abs(bearingVec1)
      } else if (Bearing_Signs == "negitive negitive" && Bearing_Values == "greater less") {
      Direction_Change <- (180 - abs(bearingVec1)) + abs(bearingVec2)
      } else if (Bearing_Signs == "negitive negitive" && Bearing_Values == "greater greater")  {
      Direction_Change <- (abs(bearingVec1) - 90) + 90 + (180 - abs(bearingVec2))
  }

 return(Direction_Change)

}

问题

当我使用该功能时,它会正确评估轴承输入(我已包含打印语句,以便您可以轻松评估)。请参阅下面的工作示例(我手动检查了它和其他人以仔细检查数学和分配等......)

analyzeGPS_DirectionChange(bearingVec1 = 100.6587, bearingVec2 = 24.66356)

[1] "positive positive"
[1] "greater less"
[1] 104.0049

但是,当我通过代表连续点的函数运行两个向量时,一些计算正确,而另一些计算错误。请参见下面的示例:

bearingVec1 <- c(1.988956, 100.658682, 24.663563, 122.423408, -30.556419, 14.702280, -74.235212, -5.619550, 78.729953, -135.463404, -2.600200)
bearingVec2 <- c(100.658682, 24.663563, 122.423408, -30.556419, 14.702280, -74.235212, -5.619550, 78.729953, -135.463404, -2.600200, -6.733987)

analyzeGPS_DirectionChange(bearingVec1, bearingVec2)

 [1] "positive positive" "positive positive" "positive positive" "positive negitive" "negitive positive" "positive negitive"
 [7] "negitive negitive" "negitive positive" "positive negitive" "negitive negitive" "negitive negitive"
 [1] "less greater" "greater less" "less greater" "greater less" "less less"    "less less"    "less less"    "less less"   
 [9] "less greater" "greater less" "less less"   
 [1]  81.33027 255.99512  82.24015 332.97983 134.74130 268.93749 111.38434  95.65050 394.19336  47.13680 184.13379

乍一看似乎有效,但是实际值答案中有一些错误,请参阅上面的第一个示例,当我手动输入方位值时正确计算 - 这些数字对应于 BearingVec1[2] 和 BearingVec2[2]在我提供的样本数据中。

当我为函数提供向量时,我不知道为什么它计算不正确。请帮我解决这个问题!

标签: rfunctionif-statementtrigonometrybearing

解决方案


问题来自if与 结合&&。从帮助 &&

'&' 和 '&&' 表示逻辑 AND 和 '|' 和'||' 表示逻辑或。较短的形式执行元素比较的方式与算术运算符大致相同。较长的形式从左到右评估,仅检查每个向量的第一个元素。

那就是您的if子句将始终回退到第一个元素。不是你想要的。

ifelse另一方面是矢量化的。因此,您可以用ifelse构造替换所有 if 子句,考虑到所有嵌套的ifs.

另一种解决方案是使用任何形式的循环仅将单个值传递给您的函数。但是,这种方法不是很优雅,并且您没有充分利用 R 的内置功能来处理向量,并且可能比重写函数以正确处理向量要慢得多,但是您可以轻松地使用您的函数:

 purrr::map2_dbl(bearingVec1, bearingVec2, analyzeGPS_DirectionChange)
 # [1]  81.33027 104.00488  82.24016  27.02017 134.74130  91.06251 248.61566
 # [8]  95.65050  34.19336  47.13680 175.86621

另一种选择是使用Vectorizewhich 向量化您的函数(基本上是通过mapply在引擎盖下执行):

 Vectorize(analyzeGPS_DirectionChange)(bearingVec1, bearingVec2)
 # [1]  81.33027 104.00488  82.24016  27.02017 134.74130  91.06251 248.61566
 # [8]  95.65050  34.19336  47.13680 175.86621

推荐阅读