如何通过转换处理R eval?

问题描述 投票:1回答:2

我对R很陌生。我正在尝试将一些列汇总到一个新列。因为只有聚合的列必须保存到DF,所以我使用transmute。

因为列名可能不同,所以我试图连接一些字符串以组成一段代码,然后使用parse和eval来处理此代码。

我放在一起的是:

transmute("aggr1" = as.numeric(val1) + as.numeric(val2), "aggr2" = as.numeric(val3) + as.numeric(val4))

如果我像这样制作一个新的数据框,它会完美地工作:

data_aggr <- df %>%
  transmute("aggr1" = as.numeric(val1) + as.numeric(val2), "aggr2" = as.numeric(val3) + as.numeric(val4))

但是如果我放在一起的字符串看起来像:

composed = "transmute(\"aggr1\" = as.numeric(val1) + as.numeric(val2), \"aggr2\" = as.numeric(val3) + as.numeric(val4))"

然后我使用:

data_aggr <- df %>%
  eval(parse(text=composed))

它不起作用。我收到错误:

error in mutate(.data, !!!dots)

我的解决方案是否可能。我做错了吗?

r eval
2个回答
1
投票

作为一般规则您几乎never想要在常规代码中使用parseeval-实际上,它们的出现应警告您您正在错误地思考问题。这些是用于低级R编程的专用工具,分析代码中应该完全没有这些工具。

首先,在您的代码中,可能造成混淆的原因是在列名周围使用了双引号,因此您认为它们是字符串。实际上并非如此! R在多个位置静默接受字符串文字,而不是变量名,并且将它们作为变量名处理

所以您的初始代码实际上等效于

transmute(aggr1 = as.numeric(val1) + as.numeric(val2), aggr2 = as.numeric(val3) + as.numeric(val4))

不带引号,这种区别对于理解正在发生的事情至关重要。


现在,如何概括这一点,以便您实际上使用不同的列名(即计算值)?简而言之,您需要在列名前面使用!!,并用:=代替=

!!导致dplyr将列名称解释为计算值,并且使用:=而不是=可以防止R将值视为函数调用参数名称(它可以解决R限制,因为!! x = y为语法上无效)。

例如:

prefix = 'aggr'
data_aggr = df %>%
  transmute(
    !! paste0(prefix, 1) := as.numeric(val1) + as.numeric(val2),
    !! paste0(prefix, 2) := as.numeric(val3) + as.numeric(val4)
  )

显然如何计算列名取决于您的特定问题。

小插图programming with dplyr中介绍了如何动态调用dplyr函数的详细信息。


0
投票

这提供了基于evalparse的解决方案。正如@Konrad Rudolph指出的那样,强烈建议不要使用这种编程。

评估/解析

我认为

data_aggr <- df %>%
  eval(parse(text=composed))

不是您要尝试做的。由于

df %>%
  eval(parse(text=composed))

类似于

eval(df, parse(text=composed))

这不会创建您想要的输出。更改

composed <- "df %>% transmute(\"aggr1\" = as.numeric(val1) + as.numeric(val2), \"aggr2\" = as.numeric(val3) + as.numeric(val4))"

然后再次运行

data_aggr <- eval(parse(text=composed))

将为您提供预期的输出。

© www.soinside.com 2019 - 2024. All rights reserved.