我在使用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())
。
答案 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!