NA 的 R 函数问题条件的长度 > 1,并且只使用第一个元素
R function problem with NA the condition has length > 1 and only the first element will be use
我有以下功能,returns 从 ID 年龄:
giveAge = function(id){
# start returns the place where any number starts in the id string
start = regexpr(id, pattern ="[0-9]")[[1]]
# age returns the age by using the year the id was born
age = ifelse(substr(id,start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id,start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id,start,start + 1)))
)
return(age)
}
例如,假设我们有一个包含四个 ID 的向量,但缺少第三个 ID。
(1975年AAHG,1991年FFCH,1955年CUM)
IDs = c("AAHG7511083A8", "FFCH9108017U2", NA, "CUM550117112")
在IDs
中使用giveAge
我们得到
> giveAge(IDs)
[1] 46 30 NA 66
这里一切都很酷,但当缺失值在向量中排在第一位时
IDs2 = c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
当应用 giveAge
到 IDs2
我得到
> giveAge(IDs2)
[1] NA NA NA NA
如果值为 NA,我尝试通过输入任意数字来解决问题,但我收到警告并且该函数未应用于整个向量:c
giveAge2 = function(id){
if(!is.na(id)){
start = regexpr(id, pattern ="[0-9]")[[1]]
age = ifelse(substr(id,start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id,start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id,start,start + 1)))
)
return(age)
} else {
return(28)
}
}
> giveAge2(IDs2)
[1] 28
Warning message:
In if (!is.na(id)) { :
the condition has length > 1 and only the first element will be used
我该如何解决这个问题?
谢谢。
在函数中,用is.na
创建一个逻辑索引。然后使用索引从输入向量中提取并分配给return值。
giveAge <- function(id){
# start returns the place where any number starts in the id string
i_na <- is.na(id)
age <- rep(NA_real_, length(id))
start <- regexpr(id[!i_na], pattern ="[0-9]")[[1]]
# age returns the age by using the year the id was born
age[!i_na] <- ifelse(substr(id[!i_na],start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id[!i_na],start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id[!i_na],start,start + 1)))
)
age
}
IDs = c("AAHG7511083A8", "FFCH9108017U2", NA, "CUM550117112")
IDs2 = c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
giveAge(IDs)
#[1] 46 30 NA 71
giveAge(IDs2)
#[1] NA 46 30 71
is.na(id)
returns TRUE
或 FALSE
id
中的每个值。由于 id
在您的示例中设置为 c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
,因此 is.na(id)
的输出将为 TRUE, FALSE, FALSE; FALSE
。
然而,if()
函数只需要一个值(单个 TRUE
或 FALSE
)。不检查其余部分:如果问题仅出现“当缺失值在向量中排在第一位时”,您可以使用 if(!is.na(id[1]))
检查第一个值是否为 NA
1) 问题中的 giveAge 代码仅根据输入的第一个元素计算开始,因此如果该元素为 NA,则所有内容均为 NA。如果 [[1]] 被删除,问题中的 giveAge 将起作用。
(giveAge2 存在上述问题,而且它正在将向量传递给 if 语句,但此类语句需要标量。)
2) 交替尝试这个。我们还删除了对包的依赖。这会从每个字符串的左侧修剪非数字,取出剩余部分的前 2 位数字并将其转换为数字,给出 2 位数字年份 yy。然后它将其转换为给出年份的 4 位数年份并从当前年份中减去它。
giveAge3 <- function(id, today = Sys.Date(), cutoff = 10) {
yy <- as.numeric(substr(trimws(id, "left", "\D"), 1, 2))
year <- yy + 1900 + 100 * (yy < cutoff)
as.numeric(format(today, "%Y")) - year
}
giveAge3(IDs)
## [1] 46 30 NA 66
giveAge3(IDs2)
## [1] NA 46 30 66
我有以下功能,returns 从 ID 年龄:
giveAge = function(id){
# start returns the place where any number starts in the id string
start = regexpr(id, pattern ="[0-9]")[[1]]
# age returns the age by using the year the id was born
age = ifelse(substr(id,start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id,start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id,start,start + 1)))
)
return(age)
}
例如,假设我们有一个包含四个 ID 的向量,但缺少第三个 ID。 (1975年AAHG,1991年FFCH,1955年CUM)
IDs = c("AAHG7511083A8", "FFCH9108017U2", NA, "CUM550117112")
在IDs
中使用giveAge
我们得到
> giveAge(IDs)
[1] 46 30 NA 66
这里一切都很酷,但当缺失值在向量中排在第一位时
IDs2 = c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
当应用 giveAge
到 IDs2
我得到
> giveAge(IDs2)
[1] NA NA NA NA
如果值为 NA,我尝试通过输入任意数字来解决问题,但我收到警告并且该函数未应用于整个向量:c
giveAge2 = function(id){
if(!is.na(id)){
start = regexpr(id, pattern ="[0-9]")[[1]]
age = ifelse(substr(id,start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id,start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id,start,start + 1)))
)
return(age)
} else {
return(28)
}
}
> giveAge2(IDs2)
[1] 28
Warning message:
In if (!is.na(id)) { :
the condition has length > 1 and only the first element will be used
我该如何解决这个问题?
谢谢。
在函数中,用is.na
创建一个逻辑索引。然后使用索引从输入向量中提取并分配给return值。
giveAge <- function(id){
# start returns the place where any number starts in the id string
i_na <- is.na(id)
age <- rep(NA_real_, length(id))
start <- regexpr(id[!i_na], pattern ="[0-9]")[[1]]
# age returns the age by using the year the id was born
age[!i_na] <- ifelse(substr(id[!i_na],start,start) == 0,
lubridate::year(Sys.Date()) - (2000 + as.numeric(substr(id[!i_na],start,start + 1))),
lubridate::year(Sys.Date()) - (1900 + as.numeric(substr(id[!i_na],start,start + 1)))
)
age
}
IDs = c("AAHG7511083A8", "FFCH9108017U2", NA, "CUM550117112")
IDs2 = c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
giveAge(IDs)
#[1] 46 30 NA 71
giveAge(IDs2)
#[1] NA 46 30 71
is.na(id)
returns TRUE
或 FALSE
id
中的每个值。由于 id
在您的示例中设置为 c(NA, "AAHG7511083A8", "FFCH9108017U2", "CUM550117112")
,因此 is.na(id)
的输出将为 TRUE, FALSE, FALSE; FALSE
。
然而,if()
函数只需要一个值(单个 TRUE
或 FALSE
)。不检查其余部分:如果问题仅出现“当缺失值在向量中排在第一位时”,您可以使用 if(!is.na(id[1]))
NA
1) 问题中的 giveAge 代码仅根据输入的第一个元素计算开始,因此如果该元素为 NA,则所有内容均为 NA。如果 [[1]] 被删除,问题中的 giveAge 将起作用。
(giveAge2 存在上述问题,而且它正在将向量传递给 if 语句,但此类语句需要标量。)
2) 交替尝试这个。我们还删除了对包的依赖。这会从每个字符串的左侧修剪非数字,取出剩余部分的前 2 位数字并将其转换为数字,给出 2 位数字年份 yy。然后它将其转换为给出年份的 4 位数年份并从当前年份中减去它。
giveAge3 <- function(id, today = Sys.Date(), cutoff = 10) {
yy <- as.numeric(substr(trimws(id, "left", "\D"), 1, 2))
year <- yy + 1900 + 100 * (yy < cutoff)
as.numeric(format(today, "%Y")) - year
}
giveAge3(IDs)
## [1] 46 30 NA 66
giveAge3(IDs2)
## [1] NA 46 30 66