错误条件长于 1 个函数 if else [编辑:按行]

Error condition longer than 1 function if else [EDIT: rowwise]

TL;DR: 我的函数没有向量化吗?我如何向量化一个函数调用其他函数与许多 if & else 语句? 非常感谢!

编辑:当在控制台中一次手动做一棵树时,该功能有效,或者在使用 dplyr::rowwise

时使用 dplyr 风格

我正在编写一个包含大量 if 和 else 的函数。

该函数根据提供(或缺少)哪些参数来决定使用哪个函数来计算树的体积。

我想像这样使用它,dplyr 风格,在大量情况下 sheet。

tree_data %>% mutate(volume = tree.volume(dbh.cm = dbh.cm, height.m= height, species.latin=species.latin, latitude= latitude)

通常缺少 crown.base.height.m 和 double.bark.mm(有没有这些参数的体积函数)。

tree.volume <- function(dbh.cm,height.m,crown.base.height.m,double.bark.mm,species.latin,latitude){
  if(grepl("^Pinus", ignore.case=TRUE, species.latin)){
    pinus_spp_vol(species.latin = species.latin,
                  dbh.cm = dbh.cm,
                  height.m = height.m,
                  latitude = latitude,
                  double.bark.mm = double.bark.mm,
                  crown.base.height.m = crown.base.height.m)
  } else if(grepl("^Picea|^Abies",ignore.case = TRUE, species.latin)){
    picea_spp_vol(dbh.cm = dbh.cm,
                  height.m = height.m,
                  latitude = latitude,
                  crown.base.height.m = crown.base.height.m)
  } else if(grepl("^Larix", ignore.case = TRUE, species.latin)){
    larix_sibirica_vol_carbonnier_1954(dbh.cm = dbh.cm,
                                       height.m = height.m,
                                       double.bark.mm = double.bark.mm,
                                       crown.base.height.m = crown.base.height.m)
  }

}

我收到警告消息:

1: In if (grepl("^Pinus", ignore.case = TRUE, species.latin)) { :
the condition has length > 1 and only the first element will be used

2: In if (species.latin == "Pinus contorta") { : the condition has length > 1 and only the first element will be used

3: In if (dbh.cm >= 4.5) { : the condition has length > 1 and only the first element will be used

4: In if (latitude >= 60) { : the condition has length > 1 and only the first element will be used

我将此解读为函数一次不处理 data.frame 中的一行...因此相信我的所有行都与第一行属于同一“类别”?

附上: 从中读取导致错误的 if 语句的第一个函数:

pinus_spp_vol <- function(species.latin, dbh.cm, height.m, crown.base.height.m, double.bark.mm, latitude){
  if(!missing(crown.base.height.m)){
    if(!missing(double.bark.mm)){
      if(species.latin!="Pinus contorta"){
        if(dbh.cm >= 4.5){ #Brandel, 1990 function 100-4. for Pines above 4.5 cm dbh.
          if(latitude >= 60){
            (10^-1.12715)*(dbh.cm^2.13211)*((dbh.cm+20)^-0.13543)*(height.m^1.58121)*((height.m-1.3)^-0.73435)*(crown.base.height.m^0.06595)*(double.bark.mm^-0.10998)
          } else {
            (10^-1.20042)*(dbh.cm^2.10263)*((dbh.cm+20)^-0.07366)*(height.m^1.99751)*((height.m-1.3)^-1.11357)*(crown.base.height.m^0.06420)*(double.bark.mm^-0.14963)
          }
        } else { #Andersson,1954 for small trees.
          if(latitude >= 60){
            0.22 + 0.08786 * (dbh.cm^2) + 0.03045 * (dbh.cm^2) * height.m + 0.002809 * dbh.cm * (height.m^2)
          } else {
            0.22 + 0.1066 * (dbh.cm^2) + 0.02085 * (dbh.cm^2) * height.m + 0.008427 * dbh.cm * (height.m^2)
          }
        }
      }
    }
  } else {
    if(species.latin== "Pinus contorta"){ #Eriksson 1973
      0.1121*(dbh.cm^2) + 0.02870*(dbh.cm^2)*height.m - 0.000061*(dbh.cm^2)*(height.m^2) - 0.09176*dbh.cm*height.m + 0.01249*dbh.cm*(height.m^2)
    } else {
      if(dbh.cm >= 4.5){#Brandel 1990, 100-01
        if(latitude >= 60){
          (10^-1.20914)*(dbh.cm^1.94740)*((dbh.cm+20)^-0.05947)*(height.m^1.40958)*((height.m-1.3)^-0.45810)
        } else {
          (10^-1.38903)*(dbh.cm^1.84493)*((dbh.cm+20)^0.06563)*(height.m^2.02122)*((height.m-1.3)^-1.01095)
        }
      } else { #Andersson,1954 for small trees.
        if(latitude >= 60){
          0.22 + 0.08786 * (dbh.cm^2) + 0.03045 * (dbh.cm^2) * height.m + 0.002809 * dbh.cm * (height.m^2)
        } else {
          0.22 + 0.1066 * (dbh.cm^2) + 0.02085 * (dbh.cm^2) * height.m + 0.008427 * dbh.cm * (height.m^2)
        }
      }
    }
  }
}

您混淆了 non-vectorized if () ... else ... 和向量化 ifelse

if () ... else ... 采用单个 (!!) 条件并根据条件是 TRUE 还是 FALSE 执行操作。如果您改为为条件传递一个(逻辑)向量,则仅选择向量的第一个元素来决定执行哪个操作。作为通知,R 将发出警告。但是,除此之外,您通常会得到错误或 non-expected 结果。

另一方面,

ifelse 是矢量化的,即检查两个条件并按元素采取操作。对于所有 TRUE 元素,选择了 TRUE 操作,对于所有 FALSE 元素,选择了 FALSE 操作。

这可以通过一个简单的例子得到最好的理解:

power2 <- function(x) x^2
power3 <- function(x) x^3

myfun_warning <- function(cyl) {
  if (cyl == 4) {
    power2(cyl)
  } else {
    power3(cyl)
  }
}

myfun_no_warning <- function(cyl) {
  ifelse(cyl == 4, power2(cyl), power3(cyl))
}

# Warning and incorrect result
myfun_warning(mtcars$cyl)
#> Warning in if (cyl == 4) {: the condition has length > 1 and only the first
#> element will be used
#>  [1] 216 216  64 216 512 216 512  64  64 216 216 512 512 512 512 512 512  64  64
#> [20]  64  64 512 512 512 512  64  64  64 512 216 512  64

# No warning and correct result
myfun_no_warning(mtcars$cyl)
#>  [1] 216 216  16 216 512 216 512  16  16 216 216 512 512 512 512 512 512  16  16
#> [20]  16  16 512 512 512 512  16  16  16 512 216 512  16