将R中的多个表达式组合成一个大表达式

3
我是新手,对于R表达式处理并不熟悉。我遇到了以下问题,希望得到任何帮助。
我正尝试生成两个单独的方程,并将它们合并为一个表达式,并将其传递给算法以找到最优值。
   OLD_PRICE    ELAST      Units    
 1  59.98        1.3        151     
 2  59.98        1.3        230     

代码:

for(i in 1:nrow(df)){
    o[i] = df$OLD_PRICE[i]
    el[i] = df$ELAST[i]
    u[i] = df$Units[i]
    assign(paste0("l",i),(substitute((x)*(1-(x-o)*el/o)*u,     list(o=o[i],el=el[i],u=u[i]))))
}

我能够生成以下两个方程式:
l1 = (x) * (1 - (x - 59.98) * 1.3/59.98) * 151
l2 = (x) * (1 - (x - 59.98) * 1.3/59.98) * 230

我的目标函数会是这样的。
eval_obj_f <- function(x){eval(l1)+eval(l2)}

我正在尝试动态地解决这个问题。比如,如果我有一个不同的4个观测值的数据集,我该如何动态生成以下目标函数?

eval(l1)+eval(l2)+eval(l3)+eval(l4)

@user4966552:你没有任何“方程式”。你有两个变量,分别为名为l1l2的表达式(在某种意义上),它们是上面“等式”的rhs。你希望在特定环境中对它们进行评估,其中存在以某种形式存在的x - IRTFM
2个回答

0
你需要使用真正的R表达式,而目前这些不是表达式,而是调用(使用is.expression或class进行检查)。我不喜欢将数据框命名为“df”,因为它也是一个函数名称,所以我使用了“prdat”:
 o <- el <- u <- numeric(2)  # if they don't exist, then the loop errors out
 for(i in 1:nrow(prdat)){
     o[i] = prdat$OLD_PRICE[i]
     el[i] = prdat$ELAST[i]
     u[i] = prdat$Units[i]
     assign(paste0("l",i), as.expression(substitute(x*(1-(x-o)*el/o)*u, 
                                                   list(o=o[i],el=el[i],u=u[i]))))
                        }

l1
#expression(x * (1 - (x - 59.98) * 1.3/59.98) * 151) # how expressions appear when printed.
l2
#expression(x * (1 - (x - 59.98) * 1.3/59.98) * 230)
exprlist <- list(l1,l2)

eval_obj_f <- function(x){sum( sapply( exprlist, eval, envir=list(x=x) ) )}
eval_obj_f(2)
#[1] 1719.569

这个看起来相当笨重。我可能会在那个数据框上应用一个函数并对结果求和。我想尝试“使用语言计算”的方法可能是有趣的,但是请看下面的代码,我认为它更符合“R的方式”。似乎更简洁……更富表现力:

func <- function(x) {apply(prdat, 1, function(z) x*(1-
                                (x-z["OLD_PRICE"])*z["ELAST"]/z["OLD_PRICE"])*z["Units"] )}
> sum( func(x=2))
[1] 1719.569

这可能比仅使用您的代码更好(但在我看来仍然比第二种方法笨重得多):

exprvec <- expression()
o <- el <- u <- numeric(2)  
 for(i in 1:nrow(prdat)){
     o[i] = prdat$OLD_PRICE[i]
     el[i] = prdat$ELAST[i]
     u[i] = prdat$Units[i]
     exprvec[[i]] <- substitute(x*(1-(x-o)*el/o)*u, 
                                list(o=o[i],el=el[i],u=u[i]))
                        }  #substitute-value gets coerced to mode-expression
# Test
> eval_obj_f <- function(x){sum( sapply( exprvec, eval, envir=list(x=x) ) )}
> eval_obj_f(2)
[1] 1719.569

问题是“如何动态生成下面的目标函数?”与l1+l2 vs. l1+l2+l3+...有关。我想在你的答案中指出sum的作用来实现这一点。 - aaryno
不确定我是否理解您的关注点。sum函数将折叠与系数数据框中的行数相同的许多值。如果您担心列表或类似列表对象外存在未指定数量的l<n>表达式,则我会同意,并建议OP将项目添加到表达式向量中,而不是使用assign - IRTFM
感谢BondedDust的解释和输入。 - gk7

-1
你可以使用省略号创建接受任意数量参数的函数:
eval_obj_f <-function(x,...){
  sum(sapply(...),function(expr) {eval(expr)})
}

举个例子,我将你的R表达式移动到一个列表中

l=list()
for(i in 1:nrow(df)){  
  o = df$OLD_PRICE[i]
  el = df$ELAST[i]
  u = df$Units[i]
  l[[i]]=substitute((x)*(1-(x-o)*el/o)*u,list(o=o,el=el,u=u))
}

现在,您可以将列表与“x”的值一起传递给您的eval_obj_f函数:
x=8.76
eval_obj_f (x,l)

1
我希望你正在努力编写一个示例来展示这个工具的实用性。如果没有,那么它只是一个注释级别的贡献。 - IRTFM
我没有对它进行负面评价,而且SO强烈反对要求人们说明他们的理由。我认为在我的提问之后你可能会将其删除,甚至考虑将其标记为“不是答案”,但最终决定它是“有用的”。显然,其他人认为它不够“有用”,愿意花费自己的积分来发送负面信息。 - IRTFM
谢谢。我是新手,渴望进步,但显然需要花更多时间产生有用的回应。 - aaryno

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接