我将一些问题简化为以下玩具代码:
cc<-c("1","2")
ff<-function(x) { list(myname=x)}
aa<-unlist(lapply(cc,ff))
bb<-sapply(cc,ff)
我希望 aa 和 bb 是相同的,但是:
> aa
myname myname
"1" "2"
> bb
$`1.myname`
[1] "1"
$`2.myname`
[1] "2"
我知道使用。但是,要应用的 NAMES 参数 -
- 它被记录为 -
用。名称逻辑;如果为 TRUE 且 X 是字符,则使用 X 作为名称 结果,除非它已经有名称。
所以在这种情况下应该没有影响,
- 在内部,它甚至没有传递给 simplify2array,因此也没有传递给最终的 unlist。
这是怎么回事?这可能是 R 问题吗?
编辑:经过进一步调查,发现差异的根本原因是sapply本质上等同于不
unlist(lapply(cc,ff)
而是
unlist(lapply(cc, ff), recursive = FALSE)
(这是确切的内部取消列表调用(。
仔细看看这个:
lapply(cc, ff)
#> [[1]]
#> [[1]]$myname
#> [1] "1"
#>
#>
#> [[2]]
#> [[2]]$myname
#> [1] "2"
lapply
本身的输出没有名称。看:
a <- lapply(cc, ff)
names(a)
#> NULL
lapply
的输出实际上是一个未命名的列表。a
的每个元素都是一个命名列表。
names(a[[1]])
#> [1] "myname"
names(a[[2]])
#> [1] "myname"
因此,实际上,USE.NAMES
将适用,sapply
会将cc
的内容分配为lapply
输出的名称,sapply
是文档中所述的薄包装器。遵循代码非常简单:
sapply
#> function (X, FUN, ..., simplify = TRUE, USE.NAMES = TRUE)
#> {
#> FUN <- match.fun(FUN)
#> answer <- lapply(X = X, FUN = FUN, ...)
#> if (USE.NAMES && is.character(X) && is.null(names(answer)))
#> names(answer) <- X
#> if (!isFALSE(simplify) && length(answer))
#> simplify2array(answer, higher = (simplify == "array"))
#> else answer
#> }
#> <bytecode: 0x036ae7a8>
#> <environment: namespace:base>