当我需要过滤data.frame,即提取满足特定条件的行时,我更喜欢使用subset
函数:
subset(airquality, Month == 8 & Temp > 90)
而不是[
函数:
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
我偏好有两个主要原因:
我发现代码从左到右读得更好。即使对R一无所知的人也可以说出上面的subset
陈述是做什么的。
因为列可以在select
表达式中称为变量,所以我可以节省一些键击。在上面的示例中,我只需使用airquality
键入subset
一次,但使用[
键入三次。
所以我生活得很幸福,到处使用subset
,因为它更短,读起来更好,甚至为我的R编码员提倡它的美丽。但昨天我的世界崩溃了。在阅读subset
文档时,我会注意到这一部分:
警告
这是一种便于交互使用的便利功能。对于编程,最好使用标准的子集函数,如[,特别是参数子集的非标准评估可能会产生意想不到的后果。
有人可以帮助澄清作者的意思吗?
首先,“交互式使用”是什么意思?我知道什么是交互式会话,而不是在BATCH模式下运行的脚本,但我不知道它应该有什么区别。
然后,你能否解释一下“论证子集的非标准评估”以及为什么它是危险的,或许可以提供一个例子?
答案 0 :(得分:229)
@James的评论很好地回答了这个问题,指出Hadley Wickham对subset
(以及类似函数) [here]的危险性的一个很好的解释。去读吧!
这是一个有点长的阅读,所以在这里记录Hadley使用的最直接解决“什么可能出错?”的问题可能会有所帮助:
Hadley建议使用以下示例:假设我们要使用以下函数对数据框进行子集化,然后重新排序:
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)
(运行它们并亲眼看看,它非常疯狂。)
答案 1 :(得分:26)
同样[
更快:
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