当我需要过滤一个data.frame,即提取满足一定条件的行时,我更喜欢使用这个subset函数:
subset
subset(airquality, Month == 8 & Temp > 90)
而不是[函数:
[
airquality[airquality$Month == 8 & airquality$Temp > 90, ]
我偏爱的主要原因有两个:
我发现代码从左到右读起来更好。即使对 R 一无所知的人也可以知道subset上面的陈述在做什么。
因为列可以在表达式中被称为变量,所以select我可以节省一些击键。在我上面的例子中,我只需要用 输入airquality一次subset,但是用 3 次[。
select
airquality
所以我过得很开心,subset到处都在使用,因为它更短,读起来更好,甚至向我的 R 程序员同事宣传它的美感。但是昨天我的世界分崩离析。在阅读subset文档时,我注意到这一部分:
警告 这是一个旨在以交互方式使用的便利功能。对于编程,最好使用像 [ 之类的标准子集函数,特别是参数子集的非标准评估可能会产生意想不到的后果。
警告
这是一个旨在以交互方式使用的便利功能。对于编程,最好使用像 [ 之类的标准子集函数,特别是参数子集的非标准评估可能会产生意想不到的后果。
有人可以帮助澄清作者的意思吗?
首先,他们所说的“ 以交互方式使用 ”是什么意思?我知道什么是交互式会话,而不是在 BATCH 模式下运行的脚本,但我看不出它应该有什么不同。
那么,您能否解释一下“ 参数子集的非标准评估 ”以及为什么它很危险,也许可以提供一个例子?
这个问题在@James 的评论中得到了很好的回答,并指出 Hadley Wickham 对[here]subset的危险(和类似的功能)的一个很好的解释。去读吧! 这是一个有点长的阅读,所以在这里记录下 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)
(运行它们,自己看看,这太疯狂了。)