从字符串中提取代数符号

时间:2013-10-14 16:01:25

标签: string r extract formula

我有一个字符串如下

str <- "- var_a + var_c - var_d"

我希望更改向量vec

中的值
 vec <- c(var_a=0, var_b=0, var_c=0, var_d=0, var_e=0)
 vec
 var_a var_b var_c var_d var_e 
    0     0     0     0     0 

根据str:每当变量具有负号时,将vec中的相应条目设置为-1,如果它具有正号为1.我的所需输出将如下所示:

var_a var_b var_c var_d var_e 
   -1     0     1    -1     0

我的想法是尝试遍历vec的所有名称并使用正则表达式来提取str中的对应符号,但我真的不知道如何获取该符号, 实例lapply(names(vec), grepl, str)我只能看到字符串中的哪个变量。

是否有更简单的方法,例如使用formulaexpression?我还查看了包Ryacas,但找不到我需要的内容。

4 个答案:

答案 0 :(得分:4)

这适用于您的示例:

splitted <- strsplit(str, " ")[[1]]
signs <- splitted[c(TRUE, FALSE)]
vars  <- splitted[c(FALSE, TRUE)]

vec[vars] <- ifelse(signs == "+", 1, -1)

第一个变量的第一个符号是肯定的,你是否会像+中一样领先str <- "+ var_a + var_c - var_d"?如果没有,你将不得不单独处理。

答案 1 :(得分:3)

使用scan读取和拆分数据。扫描读取数据并将其放入矢量中。

vec <- c(var_a=0, var_b=0, var_c=0, var_d=0, var_e=0)
ll <- scan(text=str,what='string')
## EDIT here to treat the case the first elment is not a sign
## i.e: var_a + var_c - var_d
pos <- ll %in% c('-','+')
if(length(ll[pos]) != length(ll[!pos])) ll <- append(ll,'+',0)
vec[ll[!pos]] <- ifelse(ll[pos] == '-',-1,1)

答案 2 :(得分:2)

我喜欢regex方法,但您必须小心,正则表达式与您的变量名称兼容。这会将字符串拆分为以字母字符开头的空格(您可以使用[[:alphanum:]]更灵活,但我不确定您的字符串中是否有数字......

#  Split variables
args <- strsplit( str , "(?<=[a-z])\\s" , perl = TRUE )[[1]]

#  Extract sign and convert to integer
sign <- as.integer( paste0( strtrim(args , 1 ) , 1 ) )

# Match and change the corresponding values of vec
vec[ match( substring( args , first = 3 ) , names(vec) ) ] <- sign
#var_a var_b var_c var_d var_e 
#   -1     0     1    -1     0 

答案 3 :(得分:1)

我正在考虑一种可能很慢的方法

# set up initial condition
var_a<-var_b<-var_c<-etc<-0
 varnames<-c('var_a','var_b','var_c', etc)

values<-rep(0,length(varnames))
# test one by one to see what you get, w/ apologies in advance for evalparse
for (j in 1: length(varnames) ) {
    assign(varnames[j],1)
    values[j]<- eval(parse(str))
    assign(varnames[j],0)
}

然后values中的值会告诉您字符串中变量的符号。 丑陋而有趣的设计: - )