【问题标题】:How to pass function arguments to within?如何将函数参数传递给内部?
【发布时间】:2010-11-04 12:50:47
【问题描述】:

我想知道如何将某个函数的参数传递给与 / 一起使用的函数的子部分。例如:

  myfunction <- function(dataframe,col1,col2){

  res <- within(dataframe, somenewcol <-paste(col1,"-","col2",sep=""))

  return(res)


  }

其中 col1 和 col2 是数据框中包含的列。将参数 col1 和 col2 传递给 inside 表达式的正确方法是什么?当我尝试使用它时,我得到:

粘贴错误(col1, "-", , : 找不到对象“Some_passed_col”

这是一个例子:

   dataset <- data.frame(rnorm(20),2001:2020,rep(1:10,2))
   names(dataset) <- c("mydata","col1","col2")

   myfunction <- function(dataframe,arg1,arg2){
   res <- with(dataframe, onesinglecol <- paste(arg1,"-","arg2",sep=""))
   return(res)



   }
# call function
myfunction(dataset,col1,col2)

编辑:

the following works for me now, but I cannot completely understand why... so any further explanation is appreciated:

 myfunction(dataset,arg1="col1",arg2="col2")

如果我调整

res <- with(dataframe, onesinglecol <- paste(get(arg1),"-",get(arg2),sep=""))

【问题讨论】:

  • 请完成模型示例。
  • @Dirk Eddelbuettel,谢谢提醒,给你...
  • 不可重现。我们需要一个模拟数据集和一个模拟函数。
  • 好吧,我没有设置种子,但除此之外,前两行生成了一个适合测试这个的数据集..

标签: r


【解决方案1】:

试试

   myfunction <- function(dataframe,arg1,arg2){
   dataframe["onesinglecol"] <- dataframe[[arg1]] -dataframe[[arg2]]
   return(dataframe) 
   }

并使用字符值列名称而不是未定义的对象名称来调用它:

myfunction(dataset,"col1","col2")
       mydata col1 col2 onesinglecol
1   0.6834402 2001    1         2000
2   1.6623748 2002    2         2000
3  -0.5769926 2003    3         2000  .... etc

【讨论】:

  • Thx 有效,就像我的编辑一样。但是在这里我不明白使用这些双 [[]] 背后的原因......你能解释一下它们的意思吗?
  • “[[”运算符返回列表节点的值,而“[”运算符返回包含该值的列表。在这种情况下,“值”通常是一个向量。由于算术运算适用于向量而不是列表,因此在这种情况下,您需要“[[”版本的 Extract。
  • 如果你还想使用 within() 那么试试:myfunction
  • Within 最好保存以供交互使用,而不是在其他函数中使用。
  • @Hadley:我没有异议。我觉得我像椒盐卷饼一样转身,以便提出一个“有效”的内部版本。
【解决方案2】:

我认为这是通过 ... 指令完成的: 例如:

myfunction <- function(dataframe, ...){

  var <- anotherfunction( arg1= 1, arg2 = 2 , ...)
  return(var)
}

... 是传递给“另一个函数”的附加参数的占位符。

【讨论】:

  • within() 不能那样工作。 ... 只会传递额外的参数,而 within() 期望 R 表达式进行评估。实际上,?within 表示 ... 用于某些 future 方法的参数,因此在评估表达式时可能会被忽略。我承认 OP 的 Q 不是很清楚,因此我不会对你的回答投反对票,但这不是对这个 Q 的回答。但总的来说,是的,这就是你自己传递... 的方式功能。
【解决方案3】:

您错过了col1col2 不存在于dataframe(来自您的)和用户工作区中这一事实。

基本上,with()within() 是这样工作的:

> foo <- 10
> bar <- data.frame(FOO = 10)
> FOO + foo
Error: object 'FOO' not found
> with(bar, FOO + foo)
[1] 20

在第一种情况下,未找到 FOO,因为它位于 bar 中。在第二种情况下,我们设置了一个评估表达式的环境。在那个环境中FOO 确实存在。 foo 也可以在工作区中找到。

在您的第一个示例中(请不要编辑错误消息等,向我们准确展示您运行的代码以及产生了什么错误)col1col2 在您创建的环境中不存在表达式被评估。

此外,您似乎希望将dataframe 的列(组件)的名称 存储在col1col2 中。 DWin 向您展示了使用此信息的一种方法。保持使用within() 的另一种方法是像这样使用get()

res <- within(dataframe, somenewcol <- paste(get(col1), "-", get(col2), sep=""))

根据您的额外编辑和困惑,为什么这会起作用,get() 通过它的第一个参数返回对象 namedget("foo") 将返回名为 foo 的对象(继续我上面的示例):

get("foo") ## 找到 foo 并返回 110

在您的示例中,您有一个名称为 尤其 "col1""col2" 的数据框。您将代码更改为get(arg1)(其中arg1 &lt;- "col1"),您要求get() 从评估函数时可见的评估环境中返回名称为"col1" 的对象。由于您的 dataframe 包含一个 col1 组件,这是可见的,因为 within() 已使其可用,get() 能够找到具有所需名称的对象并将其包含在表达式中。

但此时您正试图跳过太多的障碍,因为您的问题并不具体。我想您之所以问这个问题是因为我对您之前的 Q 的回答 here。该回答提出了比 attach() 更好的选择。但是你不清楚那里有什么争论或者你真正想做的事情。如果我现在知道你真正想要做什么,那么我会建议你使用上面 DWin 的答案。

您似乎不想对列/组件名称进行硬编码。如果您可以硬编码,这将是解决方案:

res <- within(dataframe, somenewcol <- paste(col1, "-", col2, sep = ""))

但鉴于您不想硬编码,您需要 get() 版本或 DWin 的解决方案。

【讨论】:

  • 感谢您的努力。是的,我想防止对 col1、col2 的名称进行硬编码。
猜你喜欢
  • 2018-09-26
  • 1970-01-01
  • 2022-11-10
  • 2015-02-17
  • 2021-09-21
  • 2015-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多