为什么“比'subset`好?

当我需要过滤data.frame,即提取符合某些条件的行时,我更愿意使用subset函数:

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

而不是[function:

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

我的偏好主要有两个原因:

  1. 我发现代码从左到右读得更好。 即使对R一无所知的人也可以知道上面的subset声明在做什么。

  2. 因为列可以被称为selectexpression式中的variables,所以我可以节省一些击键。 在我上面的例子中,我只需要用subset键入一次airquality ,而用[

所以我活得很开心,到处都是使用subset ,因为它更短,读起来更好,甚至向我的R编码者提倡它的美。 但是昨天我的世界分崩离析了。 在阅读subset文档时,我注意到这个部分:

警告

这是一个交互式使用的便利function。 对于编程,最好使用标准的子集函数,特别是参数子集的非标准评估可能会有意想不到的后果。

有人能帮助澄清作者的意思吗?

首先,“ 交互使用 ”是指什么? 我知道什么是交互式会话,而不是脚本在BATCH模式下运行,但是我不知道应该做什么区别。

那么能否解释“ 论证子集的非标准评估 ”,为什么它是危险的,也许可以举个例子呢?

这个问题在@James的评论中得到了很好的回答,指出哈德利·威克姆(Hadley Wickham)对子subset (和它的函数)危险的一个很好的解释。 去看看吧!

这是一个有点长的阅读,所以在这里logging哈德利使用的例子可能是最有帮助的,最直接地解决了“什么可能出错”的问题:

哈德利build议如下例子:假设我们想要子集,然后使用下列函数重新sorting一个dataframe:

 scramble <- function(x) x[sample(nrow(x)), ] subscramble <- function(x, condition) { scramble(subset(x, condition)) } subscramble(mtcars, cyl == 4) 

这将返回错误:

eval(expr,envir,enclos)中的错误:未find对象'cyl'

因为R不再“知道”在哪里find名为“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