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

时间:2012-03-12 14:00:45

标签: r

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

使用向量纠正行为:

a = c("A", "B", "C")
a[a == "B"]  # Returns "B"
a[sapply(a, function(x) {x == "B"})] # Returns "B"

使用NULL值纠正行为:

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(lapply())

3 个答案:

答案 0 :(得分:18)

真正的原因是sapply不知道你的函数在没有调用的情况下会返回什么。在您的情况下,函数返回logical,但由于sapply被赋予空列表,因此永远不会调用该函数。因此,它必须提供一个类型,默认为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

答案 1 :(得分:6)

功能?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()完全无关。在这两种情况下,它都返回一致的输出,一个空列表。

答案 2 :(得分:2)

实际上,他们都返回list。两者之间的唯一区别是,当您尝试索引NULL时,它总是返回NULL(即使您的索引是列表),但是当您尝试索引空向量时,它会检查索引,并实现它是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!