Почему `[` лучше чем `subset`?
Когда мне нужно отфильтровать data.frame, т.е. извлечь строки, которые удовлетворяют определенным условиям, я предпочитаю использовать subset
функция:
subset(airquality, Month == 8 & Temp > 90)
Скорее чем [
функция:
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
Есть две основные причины моего предпочтения:
Я считаю, что код читается лучше, слева направо. Даже люди, которые ничего не знают о R, могут сказать, что
subset
Заявление выше делает.Поскольку столбцы могут называться переменными в
select
Выражение, я могу сохранить несколько нажатий клавиш. В моем примере выше, мне нужно было только набратьairquality
однажды сsubset
, но три раза с[
,
Так что я жил счастливым, используя subset
везде, потому что он короче и читается лучше, даже пропагандируя его красоту моим коллегам-программистам. Но вчера мой мир распался. Читая subset
документация, я замечаю этот раздел:
Предупреждение
Это удобная функция, предназначенная для интерактивного использования. Для программирования лучше использовать стандартные функции подмножеств, такие как [, и, в частности, нестандартная оценка подмножества аргументов может иметь непредвиденные последствия.
Может ли кто-нибудь помочь прояснить, что авторы имеют в виду?
Во-первых, что они подразумевают под "для интерактивного использования"? Я знаю, что такое интерактивный сеанс, в отличие от сценария, запускаемого в режиме BATCH, но я не понимаю, какое это должно иметь значение.
Тогда, не могли бы вы объяснить "нестандартную оценку подмножества аргументов" и почему это опасно, может быть, привести пример?
2 ответа
На этот вопрос хорошо ответили в комментариях @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)
(Запустите их и убедитесь сами, это довольно безумно.)
Также [
быстрее:
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