R: «Недопустимый символ типа нижнего индекса»

В настоящее время я работаю над темами, посвященными выражениям и квазицитатам, во 2-м издании книги Hadley Advanced R. . В разделе упражнений 20.6.5 задача состоит в том, чтобы

«Реализовать функциюrange_desc(), вариант dplyr::arrange(), который по умолчанию сортирует в порядке убывания».

Играя, я заметил некоторые вещи, которые меня озадачивают. Во-первых, я просто попытался написать функцию, которая будет принимать фрейм данных и переменные, по которым можно упорядочивать в качестве входных данных. Я хотел автоматически цитировать переменные, чтобы отразить поведение dplyr::arrange().

arrange_desc2 <- function(.data, ...) {
   my_args <- enexprs(...)
   new_order <- order(.data[[my_args[[1]]]])
   return(list(my_args = my_args, new_order = new_order))
}

df <- data.frame(a = c(4, 3, 2, 1), 
                 b = c('d', 'c', 'b', 'a'))

arrange_desc2(df, a)

# $my_args
# $my_args[[1]]
# a

# $new_order
# [1] 4 3 2 1

Это работает, но, честно говоря, я не понимаю, почему: ведь я здесь символом подмножества. Копнув глубже, я заметил, что если я пишу такой код, то получаю ошибку:

arrange_desc3 <- function(.data, ...) {
   my_args <- enexprs(...)
   new_order <- order(.data[, my_args[[1]]])
   return(list(my_args = my_args, new_order = new_order))
}

arrange_desc3(df, a)
# Error in .subset(x, j) : invalid subscript type 'symbol'

Почему я могу подмножить список с символом (это то же самое, что и выражение здесь?) и почему символ явно оценивается с использованием списка в качестве среды, но только при использовании [[, а не при использовании [? Другими словами, в чем разница между:

a <- c(1, 1, 4, 3)
a[a]
# [1] 1 1 3 4
a[sym("a")] # but list(a = a)[[sym("a")]] will work!
# Error in a[sym("a")] : invalid subscript type 'symbol'

person FloHu    schedule 02.04.2018    source источник


Ответы (1)


Если мы конвертируем в symbol, то evalуатируем его

a[eval(as.symbol("a"))]
#[1] 1 1 3 4

Или то же самое с sym из rlang

a[eval(rlang::sym("a"))]
#[1] 1 1 3 4

Что касается того, почему измененный код не работал, order применяется к vector или столбцам. При использовании drop = FALSE это data.frame

person akrun    schedule 02.04.2018
comment
Но сообщение об ошибке появляется уже на этапе поднабора фрейма данных. Кроме того, я добавил к аргументу drop = TRUE, что в сочетании с [ превращает его в вектор, как и [[, так как в обоих случаях выбирается только один столбец. И я до сих пор не понимаю, почему подмножество списка с символом работает, а подмножество вектора с символом - нет. - person FloHu; 02.04.2018
comment
Извините, только что вспомнил, что drop = TRUE по умолчанию, я отредактировал свой пост соответствующим образом, разница между [ и [[ все еще сохраняется. - person FloHu; 03.04.2018