【问题标题】:Pass equation as argument into function将方程作为参数传递给函数
【发布时间】:2017-04-27 23:06:33
【问题描述】:

有人告诉我,将方程作为字符串传递并评估它们是不好的做法。我怎样才能创建一个函数,它接受一个方程并在没有字符串版本且不使用第三方包的情况下对其进行评估?

这是我的功能:

replaceFormula <- function(df, column, formula){
  df[column] <- eval(parse(text=formula), df)
  return(df)
}

这是我的用例:

set.seed(24)
dataset <- matrix(sample(c(NA, 1:5), 25, replace = TRUE), 5)
df <- as.data.frame(dataset)
replaceFormula(df, 'V5', 'V3+V4')

更新:

这也有条件吗? 我的示例函数:

replaceFactor <- function(df, column, condition, what){
  df[column] <- sapply(df[column],function(x) ifelse(eval(parse(text=condition), df), what, x))
  return(df)
}

我的用例:

set.seed(24)
dataset <- matrix(sample(c(NA, 1:5), 25, replace = TRUE), 5)
df <- as.data.frame(dataset)
replaceFactor(df, 'V5', 'V1==1', 'GOOD')

【问题讨论】:

  • 查看帮助页面'?reformulate'。
  • 根据你的新情况,我更新了我的帖子。请检查这是否是您想要的

标签: r


【解决方案1】:

看起来你已经为自己制作了一个 transform 的笨拙版本

> set.seed(24)
> dataset <- matrix(sample(c(NA, 1:5), 25, replace = TRUE), 5)
> df <- as.data.frame(dataset)
> transform(df, V5 = V3 + V4)
  V1 V2 V3 V4 V5
1  1  5  3  5  8
2  1  1  2  1  3
3  4  4  4 NA NA
4  3  4  4  3  7
5  3  1  1 NA NA

【讨论】:

  • 快速第二个问题:是否也有类似的方法将条件作为参数传递?例如我有这个功能:replaceFactor &lt;- function(df, column, condition, what){ df[column] &lt;- sapply(df[column],function(x) ifelse(eval(parse(text=condition), df), what, x)) return(df) }
  • @Blind0ne 我真的不明白你想用那个代码做什么
  • 与您的回答类似的其他选项是within(df, V5 &lt;- V3+V4)
  • @Dason 用例具有相同的数据框:replaceFactor(df, 'V5', 'V1==1', 'GOOD') 如果在另一列中满足条件,它应该只替换值
  • @akrun 不错。我更喜欢transform 版本,但我很久没有想到within,所以这是一个很好的提醒。
【解决方案2】:

我们可以将公式作为quosure 传递,并通过在dplyr 的开发版(或即将发布的0.6.0)中取消引用(!!UQ)来评估它

library(dplyr)
replaceFormula <- function(dat, Col, form){
      Col <- quo_name(enquo(Col))
      dat %>% 
          mutate(UQ(Col) := UQ(form))
  }


replaceFormula(df, V5, quo(V3 + V4)) 
#   V1 V2 V3 V4 V5
#1  1  5  3  5  8
#2  1  1  2  1  3
#3  4  4  4 NA NA
#4  3  4  4  3  7
#5  3  1  1 NA NA

更新

基于 OP 的 cmets,我们还可以传递一个表达式来评估和更改基于它的值

replaceFormulaNew <- function(dat, Col, form, what){
      Col <- enquo(Col)
      ColN <- quo_name(Col)
      what <- quo_name(enquo(what))


      dat %>% 
          mutate(UQ(ColN) := ifelse(UQ(form), what, UQ(Col)))
  }


replaceFormulaNew(df, V5, quo(V1==1), GOOD)
#   V1 V2 V3 V4   V5
#1  1  5  3  5 GOOD
#2  1  1  2  1 GOOD
#3  4  4  4 NA    4
#4  3  4  4  3 <NA>
#5  3  1  1 NA    1

replaceFormulaNew(df, V5, quo(V3 < V4), GOOD)
#   V1 V2 V3 V4   V5
#1  1  5  3  5 GOOD
#2  1  1  2  1    3
#3  4  4  4 NA <NA>
#4  3  4  4  3 <NA>
#5  3  1  1 NA <NA>

enquo 接受输入参数并将其转换为quosure,而quo_name 将其转换为字符串以在mutate 中进行评估,以将评估的输出分配给输入中指定的列

【讨论】:

  • 仅供参考,他们特别要求没有第三方软件包的解决方案
  • @docendodiscimus 我同意 OP 可能不想要第三方软件包,但我认为阅读该帖子的其他人会从中受益。此外,OP 似乎希望将公式传递给函数。
  • 这完全独立于您的回答和我的观点。不管怎样,我不介意你的回答
  • @akrun - “不将参数传递给函数”是什么意思。我很确定它将输入数据和表达式作为参数传递。只是因为它不是字符串输入,也不是我定义的函数......我只是看不出你的论点是什么。不要试图对抗......这似乎是一个奇怪的声明。
  • @Dason 我指的是 OP 定义函数的方式,我的理解是他想将它作为要评估的字符串传递。
猜你喜欢
  • 2013-01-27
  • 2011-08-18
  • 2021-04-13
  • 1970-01-01
  • 1970-01-01
  • 2011-09-13
  • 2021-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多