提问人:flodel 提问时间:3/25/2012 最后编辑:Communityflodel 更新时间:11/15/2016 访问量:108589
为什么“[”比“子集”好?
Why is `[` better than `subset`?
问:
当我需要过滤 data.frame 时,即提取满足特定条件的行,我更喜欢使用以下函数:subset
subset(airquality, Month == 8 & Temp > 90)
而不是功能:[
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
我偏爱有两个主要原因:
我发现代码从左到右读起来更好。即使是对 R 一无所知的人也能看出上面的陈述在做什么。
subset
由于列可以在表达式中称为变量,因此我可以保存一些击键。在上面的示例中,我只需要用 键入一次,但用 键入三次。
select
airquality
subset
[
所以我过得很开心,到处都在使用,因为它更短,读起来更好,甚至向我的 R 程序员同事宣传它的美感。但昨天我的世界分崩离析了。在阅读文档时,我注意到这一部分:subset
subset
警告
这是一项旨在以交互方式使用的便利功能。对于编程,最好使用像 [ 这样的标准子集函数,特别是对参数子集的非标准计算可能会产生意想不到的后果。
有人可以帮忙澄清作者的意思吗?
首先,“交互式使用”是什么意思?我知道什么是交互式会话,而不是在 BATCH 模式下运行的脚本,但我看不出它应该有什么区别。
那么,您能否解释一下“参数子集的非标准评估”以及为什么它是危险的,也许可以举个例子?
答:
这个问题在@James的评论中得到了很好的回答,指出了哈德利·威克姆(Hadley Wickham)对[这里]的危险(以及类似的功能)的出色解释。去读吧!subset
这是一本有点长的书,所以在这里记录一下哈德利使用的例子可能会有所帮助,这个例子最直接地解决了“什么会出错?”的问题:
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)
(运行它们,亲眼看看,这太疯狂了。
评论
subset(mtcars, cyl == 4)
mtcars
subset()
cyl
scramble
mtcars
cyl
subset.data.frame
condition
mtcars
subset.data.frame
enclos = parent.frame()
condition
cyl == 4
cyl
mtcars
enclos
subset(mtcars,cyl == a)
subset.data.frame
x[r, vars, drop = drop]
subset
select
[.data.frame
[
subset()
[
subset
也更快:[
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
评论
subset
[
NA
x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })
评论
with(airquality, airquality[Month == 8 & Temp > 90, ])
dplyr::filter