为什么`[`比`subset`更好?
为什么`[`比`subset`更好?
当我需要过滤数据框,即提取符合某些条件的行时,我更喜欢使用subset
函数:
subset(airquality, Month == 8 & Temp > 90)
而不是[
函数:
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
我喜欢使用的主要原因有两个:
- 我觉得代码从左到右阅读起来更好。即使不了解R的人也能看出上面的
subset
语句在做什么。 - 因为在
select
表达式中可以将列引用为变量,所以我可以省略几个按键。在上面的示例中,使用subset
时,我只需要输入一次airquality
,而使用[
时需要输入三次。
因此,我一直使用subset
,因为它更短更易读,甚至向其他R编码人员倡导其优美之处。但昨天我的世界崩溃了。当我阅读subset
文档时,我注意到这个部分:
警告
这是一个方便的函数,用于交互使用。对于编程,最好使用标准的子集函数,如 [,特别是参数子集的非标准评估可能会产生意想不到的后果。
有人可以帮忙澄清作者的意思吗?
首先,他们所说的“交互使用”是什么意思?我知道交互式会话是什么,就像批处理模式下运行的脚本一样,但我不明白它应该有什么区别。
然后,您能解释一下“参数subset的非标准评估”是什么意思,以及为什么它是危险的,可能提供一个示例吗?
admin 更改状态以发布 2023年5月23日
此外,[
更快:
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
这个问题在评论中得到了@James很好的解答,他指出了Hadley Wickham在此处对subset
(以及类似它的函数)危险性的优秀解释。去看看吧!
这是一个有点长的阅读,因此记录下Hadley用来最直接回答“出了什么问题?”问题的例子可能是有帮助的:
Hadley提出了以下示例:假设我们想要使用以下函数对数据框进行子集和重新排序:
scramble <- function(x) x[sample(nrow(x)), ] subscramble <- function(x, condition) { scramble(subset(x, condition)) } subscramble(mtcars, cyl == 4)
这将返回错误:
Error in eval(expr, envir, enclos) : object 'cyl' not found
因为R不再“知道”如何找到名为“cyl”的对象。他还指出,如果恰好存在全局环境中叫做“cyl”的对象,那真正的奇怪事情就会发生:
cyl <- 4 subscramble(mtcars, cyl == 4) cyl <- sample(10, 100, rep = T) subscramble(mtcars, cyl == 4)
(运行它们并自己看看,非常疯狂。)