R 为什么sapply()返回一个列表?

R 为什么sapply()返回一个列表?,r,R,我在使用sapply()函数时遇到了一个奇怪的行为。这个函数应该返回一个向量,但在特殊情况下,如果给它一个空向量,它将返回一个列表 向量的正确行为: a = c("A", "B", "C") a[a == "B"] # Returns "B" a[sapply(a, function(x) {x == "B"})] # Returns "B" 使用空值时的正确行为: a = NULL a[a == "B"] # Returns NULL a[sapply(a, function(x) {x

我在使用
sapply()
函数时遇到了一个奇怪的行为。这个函数应该返回一个向量,但在特殊情况下,如果给它一个空向量,它将返回一个列表

向量的正确行为:

a = c("A", "B", "C")
a[a == "B"]  # Returns "B"
a[sapply(a, function(x) {x == "B"})] # Returns "B"
使用空值时的正确行为:

a = NULL
a[a == "B"]  # Returns NULL
a[sapply(a, function(x) {x == "B"})] # Returns NULL
空向量的奇怪行为:

a = vector()
a[a == "B"]  # Returns NULL
a[sapply(a, function(x) {x == "B"})] # Erreur : type 'list' d'indice incorrect
与此语句相同的错误消息:

a[list()] # Erreur dans a[list()] : type 'list' d'indice incorrect
为什么??是虫子吗


由于这种奇怪的行为,我使用了
unlist(lappy())
实际上,它们都返回一个
列表。两者之间唯一的区别是,当您尝试索引
NULL
时,它总是返回NULL(即使您的索引是一个列表),但当您尝试索引一个空向量时,它会检查索引,并意识到它是一个
列表

a = NULL
res = sapply(a, function(x) x == "B") # Res is an empty list
a[res] # returns NULL, because any index of NULL is NULL.


a = vector()
res = sapply(a, function(x) x == "B") # Still an empty list.
a[res] # but you can't index a vector with a list!

函数
?sapply
的帮助在值中有此项

For ‘sapply(simplify = TRUE)’ and ‘replicate(simplify = TRUE)’: if
‘X’ has length zero or ‘n = 0’, an empty list.
在这两种情况下:

> length(NULL)
[1] 0
> length(vector())
[1] 0
因此
sapply()
返回:

> sapply(vector(), function(x) {x == "B"})
list()
> sapply(NULL, function(x) {x == "B"})
list()
您的错误不是来自
sapply()
,而是来自
[
,如下所示:

> a[list()]
Error in a[list()] : invalid subscript type 'list'

因此,问题与如何执行
NULL
和空向量(
vector()
)的子集设置有关。与
sapply()无关
。在这两种情况下,它都返回一致的输出,一个空列表。

造成这种情况的真正原因是
sapply
不调用它就不知道函数将返回什么。在您的情况下,函数返回一个
逻辑的
,但由于
sapply
被提供了一个空列表,因此函数永远不会被调用。因此,它必须提供一个类型,默认为
list

a = NULL
res = sapply(a, function(x) x == "B") # Res is an empty list
a[res] # returns NULL, because any index of NULL is NULL.


a = vector()
res = sapply(a, function(x) x == "B") # Still an empty list.
a[res] # but you can't index a vector with a list!
…正是出于这个原因(以及性能),引入了
vapply
。它要求您指定返回值类型(和长度)。这允许它做正确的事情。作为奖励,它也更快

sapply(LETTERS[1:3], function(x) {x == "B"}) # F, T, F
sapply(LETTERS[0], function(x) {x == "B"})   # list()

vapply(LETTERS[1:3], function(x) {x == "B"}, logical(1)) # F, T, F
vapply(LETTERS[0], function(x) {x == "B"}, logical(1))   # logical()

有关更多信息,请参见
?vapply

Protip-它从来都不是bug@ChrisBeeley-从来都不是bug,总是一个“特性”;-不过R(和S)有一堆不太理想的“特性”,这就是其中之一。
1:0
是另一个。。。