代码之家  ›  专栏  ›  技术社区  ›  Ben Bolker

替换公式/表达式中的符号

  •  1
  • Ben Bolker  · 技术社区  · 1 年前

    假设我有一个公式或其他类似表达式的对象

    ee <- a ~ b + c
    

    并希望替换(例如)符号的所有实例 b 具有 B .实现这一点的技巧是使用字符串替换:

    (ee 
       |> deparse() 
       |> gsub(pattern = "\\<b\\>", replacement = "B") 
       |> as.formula()
    )
    

    这是有效的(结果是 ee <- a ~ B + c ,根据需要)

    可以说,更好的方法是编写一个递归函数,检查特定元素是否与目标元素相同,并用替换项替换它。如果是,则在元素上调用自己。。。这是一个巨大的痛苦。有人能建议 最小的 痛苦的实现方式(例如涉及 rapply() )?

    (与 this question 关于 移除 公式中的术语…)

    1 回复  |  直到 1 年前
        1
  •  4
  •   Mikael Jagan    1 年前

    递归函数已存在: substitute

    > do.call(substitute, list(ee, list(b = quote(B))))
    a ~ B + c
    

    请注意

    > substitute(ee, list(b = quote(B)))
    ee
    

    不起作用,因为 代替 是一个特殊参数,不计算其第一个参数:

    > typeof(substitute)
    [1] "special"
    
        2
  •  1
  •   Allan Cameron    1 年前

    如果你想要一个更方便的接口,下面的递归函数就可以了,它不使用字符串解析,也不会特别痛苦

    replace_formula <- function(f, from, to, level = 1) {
      mc <- match.call()
      if(level > 1) f <- mc$f
      if(is.symbol(f) || is.function(f)) {
        if(identical(f, mc$from)) return(mc$to) else return(f)
      }
      as.call(lapply(as.list(f), function(x) {
        do.call(replace_formula, list(f = x, from = mc$from, to = mc$to, level + 1))
        }))
    }
    

    例如:

    replace_formula(a ~ b + c, from = b, to = B)
    #> a ~ B + c
    
    replace_formula(x ~ y + x|d, y, Y)
    #> x ~ Y + x | d
    
    my_formula <- y ~ cos(sin(a)) + a
    
    replace_formula(my_formula, a, A)
    #> y ~ cos(sin(A)) + A
    

    创建于2023-07-15 reprex v2.0.2