R中的sapply()和ifelse()

时间:2014-11-25 14:54:21

标签: r if-statement sapply

我遇到了将嵌套的sapply粘贴代码包装到ifelse()中的问题,该问题检查所有组件是否为非NA。当他们不在ifelse()时,sapply工作得很好......为什么会这样?

给出一些参数:

a = c(1, 2, 3)
b = c("a", "b")
c = c("X", "Y")

以下是我如何设法将所有组合粘贴在一起

as.vector(sapply(sapply(a, function(x){paste(x, b, sep = "")}), 
                 function(x){paste(x, c, sep = "")}))

输出就是这个。这正是我想要的:

[1] "1aX" "1aY" "1bX" "1bY" "2aX" "2aY" "2bX" "2bY" "3aX" "3aY" "3bX" "3bY"

但是,如果我将完全相同的代码放在ifelse()中,检查以确保参数不是NA,则输出不同。

ifelse(!is.na(a) & !is.na(b) & !is.na(c), 
       as.vector(sapply(sapply(a, function(x){paste(x, b, sep = "")}), 
                                  function(x){paste(x, c, sep = "")})), "Error")
[1] "1aX" "1aY" "1bX"

Warning messages:
1: In !is.na(a) & !is.na(b) :
  longer object length is not a multiple of shorter object length
2: In !is.na(a) & !is.na(b) & !is.na(c) :
  longer object length is not a multiple of shorter object length

为什么呢?很明显a,b和c的长度不同;我不明白为什么这在ifelse()中很重要。为了澄清,!is.na()正在检查整个向量是否为NA,而不是像c(1,NA,3)那样,因为我将使用代码在一个不会发生的环境中。我这样做是因为ifelse是较大功能的一部分,其中参数默认为NA;非NA参数的某些组合需要特定动作。例如,如果b = NA,则上面的代码应该产生ERROR。如何完成嵌套粘贴和条件检查?

2 个答案:

答案 0 :(得分:0)

老实说,在这种情况下,我不会使用ifelse而是分别使用ifelse组件。 ifelse仅返回与测试形状相同的值(因此您的初始输出仅提供3个输出),如this question中所述。我想不出简洁的方法来获得所有组合测试没有一些正则表达式,这似乎只是一个不必要的复杂功能。以下应该可以正常工作。

if(!any(is.na(c(a,b,c)))){
  as.vector(sapply(sapply(a, function(x){paste(x, b, sep = "")}), 
                   function(x){paste(x, c, sep = "")}))
}else{
  "Error"
}

答案 1 :(得分:0)

ifelse对向量进行元素检查,并在'condition'分别为'TRUE'或'FALSE'分别为'then'和'else'的特定位置使用相应的值。例如,您可以使用ifelse以位置值替换向量中的每个否定元素:

 d <- c(1, -1, 2, -2, 3, -3)
 order <- seq_along(d)
 ifelse(d < 0, order, d)
 # [1] 1 2 2 4 3 6

因此d的第一个元素不符合标准,因此它被d的第一个元素替换。然而,第二个元素符合标准,因此它被order的第二个元素替换,依此类推。这就是为什么所有向量应该具有相同的长度,如果没有,R使用其回收技术。

所以你想要做的是使用一个简单的if语句

a <- c(1, 2, 3)
b <- c("a", "b")
d <- c("X", "Y")
if (all(!is.na(c(a, b, d))))  
    as.vector(sapply(sapply(a, function(x){paste(x, b, sep = "")}), 
                                 function(x) {paste(x, d, sep = "")})) else 
    "Error"
# [1] "1aX" "1aY" "1bX" "1bY" "2aX" "2aY" "2bX" "2bY" "3aX" "3aY" "3bX" "3bY"

d <- NA
if (all(!is.na(c(a, b, d))))  
    as.vector(sapply(sapply(a, function(x){paste(x, b, sep = "")}), 
                                 function(x) {paste(x, d, sep = "")})) else 
    "Error"
# [1] "Error"

但是,您的代码难以阅读,您可以通过以下代码提高可读性:

a <- c(1, 2, 3)
b <- c("a", "b")
d <- c("X", "Y")
if (all(!is.na(c(a, b, d)))) apply(expand.grid(a, b, d), 1, paste, collapse = "") else "Error"
# [1] "1aX" "2aX" "3aX" "1bX" "2bX" "3bX" "1aY" "2aY" "3aY" "1bY" "2bY" "3bY"

d <- NA
if (all(!is.na(c(a, b, d)))) apply(expand.grid(a, b, d), 1, paste, collapse = "") else "Error"
# [1] "Error"

expand.grid创建三个向量的所有组合。 apply遍历所有行(这是第一个维度,这就是1作为第二个参数应用然后将paste应用于每一行的原因。

希望有所帮助。