Почему `[` лучше чем `subset`? - PullRequest
387 голосов
/ 25 марта 2012

Когда мне нужно отфильтровать data.frame, т.е. извлечь строки, которые удовлетворяют определенным условиям, я предпочитаю использовать функцию subset:

subset(airquality, Month == 8 & Temp > 90)

Вместо функции [:

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

Есть две основные причины моего предпочтения:

  1. Я считаю, что код читается лучше слева направо. Даже люди, которые ничего не знают о R, могут сказать, что делает вышеприведенное утверждение subset.

  2. Поскольку столбцы могут называться переменными в выражении select, я могу сохранить несколько нажатий клавиш. В моем примере выше мне нужно было набрать airquality только один раз с subset, но три раза с [.

Так что я жил счастливо, везде использовал subset, потому что он короче и лучше читается, даже отстаивая его красоту среди моих коллег-программистов. Но вчера мой мир распался. Читая документацию subset, я замечаю этот раздел:

Внимание

Это удобная функция, предназначенная для интерактивного использования. Для программирования лучше использовать стандартные функции подмножеств, такие как [, и, в частности, нестандартная оценка подмножества аргументов может иметь непредвиденные последствия.

Может ли кто-нибудь помочь прояснить, что имеют в виду авторы?

Во-первых, что они подразумевают под " для интерактивного использования "? Я знаю, что такое интерактивный сеанс, в отличие от сценария, запускаемого в режиме BATCH, но я не понимаю, какое это должно иметь значение.

Тогда, не могли бы вы объяснить " нестандартная оценка подмножества аргументов " и почему это опасно, может быть, привести пример?

Ответы [ 2 ]

232 голосов
/ 25 марта 2012

На этот вопрос хорошо ответили в комментариях @James, указывая на превосходное объяснение Хэдли Уикхемом опасности subset (и подобных ей функций) [здесь] .Прочтите это!

Это довольно длинное чтение, поэтому может быть полезно записать здесь пример, который использует Хэдли, который наиболее непосредственно затрагивает вопрос "что может пойти не так?":

Хэдли предлагает следующий пример: предположим, что мы хотим создать подмножество, а затем переупорядочить фрейм данных, используя следующие функции:

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

Это возвращает ошибку:

Ошибка в eval (expr, envir, enclos): объект 'cyl' не найден

, потому что R больше не «знает», где найти объект с именем «cyl».Он также указывает на действительно странные вещи, которые могут произойти, если случайно в глобальной среде появится объект с именем 'cyl':

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(Запустите их и убедитесь сами, это довольно безумно).

27 голосов
/ 05 апреля 2014

Также [ быстрее:

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100
...