Подтвердить что ты не робот

Почему sapply() возвращает список?

Я столкнулся с необычным поведением в R с помощью функции sapply(). Эта функция должна возвращать вектор, но в специальном случае, когда вы даете ему пустой вектор, он возвращает список.

Правильное поведение с вектором:

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

4b9b3361

Ответ 1

Настоящая причина в том, что 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.

Ответ 2

Справка для функции ?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(). В обоих случаях он возвращает согласованный вывод, пустой список.

Ответ 3

На самом деле оба они возвращают 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!