r语言 - 在应用 FUN 返回列表或 NA 时控制嵌套列表的结构



我有一个向量v和矩阵m,并使用 apply 从函数cor.test中提取结果的子集(vm列之间的相关性)。

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 返回与测试形状相同的值

最新更新