2017-08-25 33 views
-1

我有character中的表达式,这些表达式应该在data.table(不重要的上下文中)中进行评估。 为了确保所有需要的列都存在,我想提取R表达式中的所述列。如何从R表达式中提取要在data.frame上下文中进行评估的变量

我想要什么:

library(data.table) 
DT <- data.table(p001=rnorm(10),p002=rnorm(10),p003=rnorm(10)) 
expr <- 'p001+mean(p001,na.rm=TRUE)-weighted.mean(p002,w=p003)+someRandomOtherColumn' 

# DT[,test:=p001+mean(p001,na.rm=TRUE)-weighted.mean(p002,w=p003)+someRandomOtherColumn] 
# would fail as p004 is not in the columns 

基本上我正在寻找一种方式(可能是一个正则表达式),它将从exprp001,p002,p003,someRandomOtherColumn提取。

我就可以了看法: 我看到它的方式,我应该能够捕捉到p001,p001,TRUE,p002,p003,someRandomOtherColumn一些正则表达式,将内f(,)捕捉的东西,然后筛选“允许的”列名(TRUE不是在案件)。

嵌套f(,,)不是一个问题,因为我可以调用相同的函数递归和嵌套f(,(),)也很好。

我有什么: 从现在这就是我,这可以做的工作,但这种感觉不好

expr <- 'p001+mean(p001,na.rm=TRUE)-weighted.mean(p002,w=p003)+someRandomOtherColumn' 
clean <- function(string) gsub(string, pattern='[_|\\.|a-zA-z]+\\(([^)]*)\\)', replacement='\\1', perl=TRUE) 
clean(expr) 
[1] "p001+p001,na.rm=TRUE-p002,w=p003+someRandomOtherColumn" 
# Then I can remove =* than split on ,|+|-|* 
+0

如果你只想进去'F中的值()','p004'不应该在预期的结果。 @Cath,我认为在这种情况下'\\ bp \\ d + \\ b'将会过度匹配。必须有自定义边界。 –

+0

@statquant你能保证'f(...)'里面没有'('和')'吗? –

+1

@WiktorStribiżew可以嵌套'f()',但这很好,我可以递归调用相同的函数 – statquant

回答

3

当您添加~到你的表情,你可以创建一个有效的r ...式表达:

expr <- '~ p001+mean(p001,na.rm=TRUE)-weighted.mean(p002,w=p003)+someRandomOtherColumn' 

该字符串可被转换为一个公式与as.formula。此后,变量名可以用all.vars提取:

all.vars(as.formula(expr)) 
# [1] "p001"    "p002"    "p003"    "someRandomOtherColumn" 
+0

LOL非常聪明!希望我不会找到一个反例 – statquant

+0

@statquant谢谢。请注意,这种方法比使用regex更强大,因为它使用了R的表达式解析器。 –

+0

不知道为什么我得到了低估...无论如何谢谢 – statquant

相关问题