错误条件长于 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
TL;DR: 我的函数没有向量化吗?我如何向量化一个函数调用其他函数与许多 if & else 语句? 非常感谢!
编辑:当在控制台中一次手动做一棵树时,该功能有效,或者在使用 dplyr::rowwise
我正在编写一个包含大量 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