【问题标题】:When to use 'with' function and why is it good?什么时候使用'with'功能,为什么它很好?
【发布时间】:2017-07-06 03:02:31
【问题描述】:

使用with() 有什么好处?在帮助文件中,它提到它在从数据创建的环境中评估表达式。这样做有什么好处?创建一个环境并在其中评估它是否比仅在全球环境中评估它更快?还是我还缺少其他东西?

【问题讨论】:

  • 主要用于在数组名称较长时节省击键。但这是题外话,因为许多好的问题会根据专家经验产生一定程度的意见,但这个问题的答案往往几乎完全基于意见,而不是事实、参考资料或特定专业知识。
  • 不要删除。社区将通过投票和参与来决定。
  • @BenBolker 是从 with() 的帮助文件中复制而来的
  • 这是大多数 R 学习者最终会遇到的一个很好且有价值的问题,所以让我们都想出一个非主题的措辞并保持开放。
  • 这是一个愚蠢的例子。也许我会试着把它改成更好的东西。

标签: r syntax keyword


【解决方案1】:

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)

但是,如果(出于某种奇怪的原因)我们想要找到 cyl + disp + wtmean,就会出现问题,因为 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))

with(data, foo(...)) 中包装foo() 让我们可以使用任何函数foo 好像 它有一个data 参数——也就是说我们可以使用不带引号的列名,防止重复的@ 987654342@或data_name[, "column_name"]

何时使用with

在您喜欢交互式(R 控制台)和 R 脚本时使用 with 以节省输入并使您的代码更清晰。您需要为单个命令重新键入数据框名称的频率越高(数据框名称越长!),使用with 的好处就越大。

另请注意,with 不限于数据帧。来自?with

对于默认的with 方法,它可以是环境、列表、数据框或sys.call 中的整数。

我不经常使用环境,但我发现with 非常方便。

当您只需要一行结果时

正如@Rich Scriven 在 cmets 中所建议的那样,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.frames的情况下,transform也不错。)

在包中

不要在 R 包中使用withhelp(subset) 中有一个警告,它可能同样适用于 with

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

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

with 的替代品

不要使用attach

许多(大部分过时的)R 教程使用attach 来避免重新键入数据框名称,方法是使列可访问全局环境。 attach is widely considered to be bad practice and should be avoided。附加的主要危险之一是,如果单独修改数据列,它们可能会变得不同步。 with 避免了这个陷阱,因为它一次调用一个表达式。 Stack Overflow 上有很多很多问题,新用户正在学习旧教程并因为attach 而遇到问题。简单的解决方案总是不要使用attach

一直使用with 似乎太重复了

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

【讨论】:

  • 谢谢,这很有意义。
  • 在使用rle 时也非常有用。您无需分配rle 即可访问这些值。示例:with(rle(data), lengths[values > 1])。无论如何,我觉得它非常有用。
【解决方案2】:

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

with(mtcars, plot(wt, qsec))

而不是

plot(mtcars$wt, mtcars$qsec)

前者在mtcars data.frame 中查找wtqsec。当然

plot(qsec~wt, mtcars)

更适合带有 data= 参数的绘图或其他函数。

【讨论】:

  • 为了节省输入,您还可以使用transform 和/或within
  • @Rentrop 你能给我们举一个transform和/或within的例子吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-19
  • 2013-05-28
  • 2010-12-28
相关资源
最近更新 更多