问题 何时使用'with'功能,为什么它好?


使用有什么好处 with()?在帮助文件中,它提到它在从数据创建的环境中评估表达式。这有什么好处?创建环境并在那里评估它是否更快,而不是仅仅在全球环境中评估它?或者还有其他我想念的东西?


12850
2018-02-16 19:59


起源

主要是为了在拥有长数组名称时保存击键。但这是偏离主题的,因为许多好的问题会根据专家经验产生一定程度的意见,但这个问题的答案几乎完全基于意见,而不是事实,参考或具体的专业知识。 - Pierre Lafortune
不要删除。社区将通过投票和参与决定。 - Pierre Lafortune
从with()的帮助文件复制的@BenBolker - Kristofersen
这是大多数R学习者最终会遇到的一个好的和有价值的问题,所以让我们都提出一个非主题的措辞并保持开放。 - smci
这是一个愚蠢的例子。也许我会尝试将其改为更好的东西。 - Ben Bolker


答案:


with 是没有的函数的包装器 data 论据

有许多功能可以处理数据帧并采用 data 参数,以便每次引用列时都不需要重新键入数据框的名称。 lmplot.formulasubsettransform 只是几个例子。

with 是一般目的 包装纸 让你使用任何函数,就好像它有一个数据参数。

使用 mtcars 数据集,我们可以使用或不使用data参数来拟合模型:

# this is obviously annoying
mod = lm(mtcars$mpg ~ mtcars$cyl + mtcars$disp + mtcars$wt)

# this is nicer
mod = lm(mpg ~ cyl + disp + wt, data = mtcars)

但是,如果(出于一些奇怪的原因)我们想找到 mean 的 cyl + disp + wt,有一个问题,因为 mean 没有类似的数据参数 lm 确实。这就是问题所在 with 地址:

# without with(), we would be stuck here:
z = mean(mtcars$cyl + mtcars$disp + mtcars$wt)

# using with(), we can clean this up:
z = with(mtcars, mean(cyl + disp + wt))

包皮 foo() 在 with(data, foo(...)) 让我们使用任何功能 foo  仿佛 它有一个 data 参数 - 也就是说我们可以使用不带引号的列名,防止重复 data_name$column_name 要么 data_name[, "column_name"]

什么时候用 with

使用 with 以交互方式和R脚本保存输入并使代码更清晰。您需要为单个命令重新键入数据框名称的频率越高(数据帧名称越长!),使用的好处就越大 with

另请注意 with 不限于数据帧。从 ?with

对于默认值 with 方法,这可以是环境,列表,数据框或整数,如 sys.call

我不经常使用环境,但是当我这样做时,我找到了 with 非常便利。

当您只需要一行结果时

正如@Rich Scriven在评论中所说, with 当你需要使用类似的结果时,它会非常有用 rle。如果你只需要一次结果,那就是他的榜样 with(rle(data), lengths[values > 1]) 让你使用 rle(data) 结果匿名。

何时避免 with

当有  一个 data 论据

很多功能都有 data 当你调用它时,参数使用它不仅仅是更简单的语法。大多数建模功能(如 lm),以及其他许多人(ggplot!)用提供的东西做很多事情 data。如果你使用 with  代替 一个 data 参数,您将限制可用的功能。 如果有的话 data 论证,使用 data 争论,不是 with

添加到环境中

在上面的例子中,结果被分配给了全球环境(bar = with(...))。做作业  列表/环境/数据,你可以使用 within。 (如果是 data.framestransform 也很好。)

在包中

不要用 with在R包中。有一个警告 help(subset) 这也适用于 with

警告 这是一种便于交互使用的便利功能。对于编程,最好使用标准的子集函数 [特别是论证子集的非标准评估可能会产生意想不到的后果。

如果你使用构建R包 with,当你检查它时,你可能会得到关于使用没有可见绑定的变量的警告或注释。这将使CRAN无法接受包。

替代品 with

不要用 attach

许多(大多数是过时的)R教程使用 attach 避免通过使列可供全局环境访问来重新键入数据框名称。 attach 被广泛认为是不好的做法,应该避免。附加的主要危险之一是,如果单独修改数据列,则数据列可能会变得不同步。 with 避免这个陷阱,因为它一次调用一个表达式。 Stack Overflow上有很多很多问题,其中新用户正在关注旧教程并因此而遇到问题 attach。简单的解决方案始终如一 不要用 attach

运用 with 所有的时间似乎都太重复了

如果您正在执行许多数据操作步骤,您可能会发现自己开始使用每行代码 with(my_data, ...。你可能会认为这种重复几乎和不使用一样糟糕 with。这俩 data.table 和 dplyr 软件包提供了非重复语法的高效数据操作。我鼓励你学会使用其中一个。两者都有出色的文档。


8
2018-02-16 20:56



谢谢,这很有道理。 - Kristofersen
它在使用时也非常有用 rle。您可以访问值而无需分配 rle。例: with(rle(data), lengths[values > 1])。无论如何,我发现它非常有用。 - Rich Scriven


当我不想继续输入时,我会使用它 dataframe$。例如

with(mtcars, plot(wt, qsec))

而不是

plot(mtcars$wt, mtcars$qsec)

前者抬起头来 wt 和 qsec 在里面 mtcars data.frame。当然

plot(qsec~wt, mtcars)

更适合拍摄的情节或其他功能 data= 论据。


5
2018-02-16 20:04



为了节省打字,您也可以使用 transform 和/或 within - Rentrop