我有许多类似于此的公式字符串:
str <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
有很多括号不需要在那里,(A*J - J*G)/Z
就足够了。R中是否有可以解决这个问题的函数或包?
我也尝试了 R 表达式的函数,as.formula
但没有找到我需要的。
我有许多类似于此的公式字符串:
str <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
有很多括号不需要在那里,(A*J - J*G)/Z
就足够了。R中是否有可以解决这个问题的函数或包?
我也尝试了 R 表达式的函数,as.formula
但没有找到我需要的。
我们可以使用 R 解析器来完成这项工作。诀窍是 R 根据解析树知道何时需要括号,因此我们可以简单地将它们从树中删除:
看到这个:
simplify <- function(e)
{
if( mode(e) %in% c("name","numeric") ) return(e)
op <- as.character(e[[1]])
if( op == "(" ) return(simplify(e[[2]]))
if( op %in% c("+","-","*","/","^") ) return(call(op, simplify(e[[2]]), simplify(e[[3]])))
}
simplifytext <- function(s) deparse(simplify(parse(text=s)[[1]]))
输入:
str <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
str2 <- gsub("-", "/", gsub("*", "+", str, fixed=TRUE))
结果:
> str2
[1] "( (( A ) + J ) / (( J ) + G ) ) / Z "
> simplifytext(str)
[1] "(A * J - J * G)/Z"
> simplifytext(str2)
[1] "(A + J)/(J + G)/Z"
这里有几种方法:
R解析
rmParen <- function(e) {
if (length(e) > 1) {
if (identical(e[[1]], as.symbol("("))) e <- e[[2]]
if (length(e) > 1) for (i in 1:length(e)) e[[i]] <- Recall(e[[i]])
}
e
}
s <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
rmParen(parse(text = s)[[1]])
最后一行返回:
(A * J - J * G)/Z
这在我尝试过的所有情况下都有效,但你可能想再测试一下。
如果你想要一个字符串作为返回值,那么使用deparse
as in deparse(rmParen(parse(text = s)[[1]]))
。请注意,deparse
它的width.cutoff
参数默认设置为 60,但如果实际表达式超过该长度,则可以将其设置为更大。
里亚卡斯
library(Ryacas)
s <- "( (( A ) * J ) - (( J ) * G ) ) / Z "
Simplify(s)
最后一行返回:
expression((A - G) * J/Z)
请注意,它实际上是调用计算的 print 方法,因此如果要保存它,请尝试使用yacas(Simplify(s))$text
or as.character(yacas(Simplify(s)))
。
添加:Ryacas 解决方案。