我有一个向量v
和矩阵m
,并使用 apply 从函数cor.test
中提取结果的子集(v
和m
列之间的相关性)。
set.seed(1)
m <- matrix(runif(12), nrow = 3)
v <- 3:1
res <- apply(m, 2, function(x) {
cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
})
这是一个嵌套的列表列表,其长度等于m
中的列数 - 并且在我希望作为输出的结构中(2 级列表)。
> str(res)
List of 4
$ :List of 3
..$ statistic: Named num 8
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0
..$ estimate : Named num -1
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 2
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num 0.5
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 0
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0
..$ estimate : Named num 1
.. ..- attr(*, "names")= chr "rho"
$ :List of 3
..$ statistic: Named num 6
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num -0.5
.. ..- attr(*, "names")= chr "rho"
我想在应用循环中过滤每个cor.test
结果,比如 p.value,并返回 NA 以指示过滤结果(保留结果的长度,这里四个)。
res <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value < 0.1, list(tmp), NA)
})
我的问题是我们现在得到一个 3 级列表结构
res2 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value < 0.1, list(tmp), NA)
})
> str(res2)
List of 4
$ :List of 1
..$ :List of 3
.. ..$ statistic: Named num 8
.. .. ..- attr(*, "names")= chr "S"
.. ..$ p.value : num 0
.. ..$ estimate : Named num -1
.. .. ..- attr(*, "names")= chr "rho"
$ : logi NA
$ :List of 1
..$ :List of 3
.. ..$ statistic: Named num 0
.. .. ..- attr(*, "names")= chr "S"
.. ..$ p.value : num 0
.. ..$ estimate : Named num 1
.. .. ..- attr(*, "names")= chr "rho"
$ : logi NA
只有当apply
的第一个结果是NA时,结果结构才是想要的,显然apply
可以将未过滤的结果拟合到结构中。
res3 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
ifelse(tmp$p.value > 0.1, list(tmp), NA) #'invert' the test
})
>res3
List of 4
$ : logi NA
$ :List of 3
..$ statistic: Named num 2
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num 0.5
.. ..- attr(*, "names")= chr "rho"
$ : logi NA
$ :List of 3
..$ statistic: Named num 6
.. ..- attr(*, "names")= chr "S"
..$ p.value : num 0.667
..$ estimate : Named num -0.5
.. ..- attr(*, "names")= chr "rho"
我试图返回ifelse(tmp$p.value < 0.1, tmp, NA)
,徒劳地ifelse(tmp$p.value < 0.1, list(tmp), list(NA))
。
我找到的唯一解决方案是在apply
之外分配NA
:
res4 <- apply(m, 2, function(x) {
cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
})
res4[sapply(res4, "[[", 2) > 0.1] <- NA
显然,我错过了一些关于应用程序内部工作原理的东西。
您的问题不在于apply
,而在于ifelse
。如果您改用if () {} else {}
,它将按预期方式工作
res3 <- apply(m, 2, function(x) {
tmp <- cor.test(x, v, method = 'spearman', exact = F)[c(1,3,4)]
if (tmp$p.value < 0.1) { return(tmp) } else { return(NA) }
})
str(res3)
# List of 4
# $ :List of 3
# ..$ statistic: Named num 8
# .. ..- attr(*, "names")= chr "S"
# ..$ p.value : num 0
# ..$ estimate : Named num -1
# .. ..- attr(*, "names")= chr "rho"
# $ : logi NA
# $ :List of 3
# ..$ statistic: Named num 0
# .. ..- attr(*, "names")= chr "S"
# ..$ p.value : num 0
# ..$ estimate : Named num 1
# .. ..- attr(*, "names")= chr "rho"
# $ : logi NA
注意来自ifelse
的文档
ifelse 返回与测试形状相同的值