将多个字符列转换为 R 数据框中的表达式

Converting multiple character columns to expressions in R dataframe

我有一个数据框:

Column1 | Column2 | Column3 |       Calc1       | Calc2             |
   1    |    2    |   4     | Column1 + Column2 | Column3 + Column1 |
   7    |    6    |   3     | Column1 + Column2 | Column3 + Column1 |
   9    |    9    |   10    | Column1 + Column2 | Column3 + Column1 |

Column1、Column2、Column3 是“数字”。 Calc1 和 Calc2 是“字符”。

我还有一个名为 ColNameList 的列名列表,其中包含 c("Calc1", "Calc2")。

我想应用一些将字符值转换为实际 R 表达式的函数。我希望此函数应用于的列必须由列名列表通知(即检查 ColNameList 中的列名列表,然后将这些列名与数据框中的列匹配,然后应用函数将字符转换为表达式。)

我的预期输出是这样的:

Column1 | Column2 | Column3 | Calc1   | Calc2   |
   1    |    2    |   4     |    3    |    5    |
   7    |    6    |   3     |    13   |    10   |
   9    |    9    |   10    |    18   |    19   |

我试过:

df1 <- df1(apply(df1[,ColNameList],2, function(x) eval(parse(text=df1$x))))

我环顾四周并发现了类似的问题,但我似乎无法对其他解决方案进行逆向工程以适应我的情况;特别是要求该函数仅适用于 ColNameList 中列出的列。

在 data.table 中它可以正常工作:

library(data.table)
setdT(df)

df[, c1 := eval(parse(text = Calc1))]

如果您同时想要两者,那么:

a[, `:=` (c1 = eval(parse(text = Calc1)), c2 = eval(parse(text = Calc2)))]

使用 eval + str2expression

的基础 R 选项
transform(
  df,
  Calc1 = eval(str2expression(Calc1)),
  Calc2 = eval(str2expression(Calc2))
)

给予

  Column1 Column2 Column3 Calc1 Calc2
1       1       2       4     3     5
2       7       6       3    13    10
3       9       9      10    18    19

更新

如果您有一个要应用于列的函数 f,这里可能是一个选项。假设 f 给出如下

f <- function(x, y) x + y^2

当我们运行

as.data.table(df)[
  ,
  c(cols) := lapply(
    .SD[, cols, with = FALSE],
    function(x) {
      do.call(
        f,
        unname(.SD[, unlist(strsplit(unique(x), "\s\+\s")), with = FALSE])
      )
    }
  )
][]

我们会得到

   Column1 Column2 Column3 Calc1 Calc2
1:       1       2       4     5     5
2:       7       6       3    43    52
3:       9       9      10    90    91

我找到了一个解决方案,它接受列名列表,并使用它来识别给定数据框中的列,然后将给定列中的字符值转换为实际的 R 表达式。此解决方案很有用,因为它可以泛化为接受不同的表达式,而不仅仅是求和。

解决方法如下:

Column1 <- c(1,7,9)
Column2 <- c(2,6,9)
Column3 <- c(4,3,10)
Calc1 <- c("Column1 + Column2", "Column1 + Column2", "Column1 + Column2")
Calc2 <- c("Column3 + Column1", "Column3 + Column1", "Column3 + Column1")

df <- data.frame(Column1,Column2,Column3,Calc1,Calc2)

ColNameList <- c("Calc1", "Calc2")



df2 <- df %>%
  mutate(across(ColNameList, ~ eval(str2expression(.))))