lapply 和 ifelse 不能按预期工作

lapply and ifelse together not working as expected

我正在写一个关于 R 的文档,我想出了一个我无法理解的例子。让我们这样说:

mylist <- list(8, 1:10, c(4,7,25), matrix(1:30, ncol = 5), "my name is not Donald")
lapply(1:length(mylist), function(x) ifelse(is.numeric(mylist[[x]]), 
  mylist[[x]]*2, mylist[[x]]))

我本以为我的列表中的数字元素是 2-folded 而字符向量保持原样。相反,列表中数字元素的结果只是每个元素的第一个组成部分,就好像 ifelse 的 TRUE 条件(即 1)接管了 lapply 的 x 索引一样。谁能告诉我这背后的逻辑,我应该输入什么? 非常感谢。 最好, 大卫

1) if 我们这里要if,而不是ifelse。也简化了代码。

f <- function(x) if (is.numeric(x)) x*2 else x
lapply(mylist, f)

给予:

[[1]]
[1] 16

[[2]]
 [1]  2  4  6  8 10 12 14 16 18 20

[[3]]
[1]  8 14 50

[[4]]
     [,1] [,2] [,3] [,4] [,5]
[1,]    2   14   26   38   50
[2,]    4   16   28   40   52
[3,]    6   18   30   42   54
[4,]    8   20   32   44   56
[5,]   10   22   34   46   58
[6,]   12   24   36   48   60

[[5]]
[1] "my name is not Donald"

2) S3 尽管在这种情况下这可能有点太复杂而无法保证,但如果我们有更大的 类 集合,它可能会有用,它是还表明这可以在没有任何 if 使用 S3 的情况下完成。为此,我们定义了一个带有数字和默认方法的 S3 泛型,然后 S3 将自动分派适当的方法。

dble <- function(x, ...) UseMethod("dble")
dble.numeric <- function(x, ...) 2 * x
dble.default <- function(x, ...) x

lapply(mylist, dble)

3) tryCatch 另一种不使用 if 的方法是将参数加倍,如果它引发错误则捕获它。同样,在这种情况下这可能太复杂而无法保证,但它说明了如果实际情况更复杂可以做什么。

f2 <- function(x) tryCatch(2 * x, error = function(e) x)
lapply(mylist, f2)

4) rrapply rrapply包中的rrapply函数可以指定一个条件,使得该函数只应用于满足它的元素。

library(rrapply)

rrapply(mylist, is.numeric, function(x) 2 * x)

5) modify_if purrr 包还有一个函数,它只会修改满足条件的元素。

library(purrr)

modify_if(mylist, is.numeric, `*`, 2)

问题是条件只创建一个 TRUE,而是尝试这样的事情:

#Code
lapply(1:length(mylist),
       function(x) ifelse(lapply(mylist[[x]],is.numeric),
                          mylist[[x]]*2, mylist[[x]]))

问题是矩阵结构会丢失,所以@G.Grothendieck的答案会是更好的选择。