R - 使用非标准评估检查字符串是否是有效的数学表达式

2023-12-22

我想检查下面的字符串是否是有效的数学表达式:

s1 = 'sin(x)'
s2 = 'sin(x*m)'
s3 = 'sin'
s4 = 'sin(xm)'

我所说的“有效”是指该表达式是以下内容的组合

  1. 运算符(必须与变量或常量结合使用)
  2. 变量x and/or m
  3. 常数。

根据这个定义s1 and s2有效同时s3 and s4不是。

为了确定字符串是否有效,我编写了一个函数checkFxn首先尝试将字符串转换为调用或其一部分。如果成功,它将递归调用树并检查上述条件。如果满足条件,则按原样返回调用。如果不是,则会抛出错误。

checkFxn <- function(x) {

  lang <- str2lang(x)

  checkFxn2 <- function(y) {

    if(is.name(y)) {

      stopifnot(deparse(y) %in% c('x', 'm'))

    } else if(is.call(y)) {

      stopifnot(is.function(eval(y[[1]])) | is.primitive(eval(y[[1]])))

      lapply(y[-1], checkFxn2)

    } else {

      stopifnot(is.logical(y) | is.numeric(y) | is.complex(y))

    }

    return(y)

  }

  checkFxn2(lang)

}


#Applying checkFxn to s1-4
lapply(list(s1,s2,s3,s4), function(x) {try(checkFxn(x), silent = T)})
[[1]]
sin(x)

[[2]]
sin(x * m)

[[3]]
[1] "Error in checkFxn2(lang) : deparse(y) %in% c(\"x\", \"m\") is not TRUE\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in checkFxn2(lang): deparse(y) %in% c("x", "m") is not TRUE>

[[4]]
[1] "Error in FUN(X[[i]], ...) : deparse(y) %in% c(\"x\", \"m\") is not TRUE\n"
attr(,"class")
[1] "try-error"
attr(,"condition")
<simpleError in FUN(X[[i]], ...): deparse(y) %in% c("x", "m") is not TRUE>

它似乎按预期工作,但我对使用持谨慎态度eval并想知道是否有人可以建议使用它的替代方案?我知道它遵循通常的词法范围规则,所以我担心它评估全局环境中的变量 - 有没有办法限制其范围?我读过有关的章节非标准评价 http://adv-r.had.co.nz/Computing-on-the-language.html#scoping-issues但我不明白。

另外,有没有办法识别基函数或基元是否是数学运算符?我想使用比is.function and is.primitive.


Step 1:决定什么是“数学运算符”。一种选择是从S4 泛型 https://stat.ethz.ch/R-manual/R-devel/library/methods/html/S4groupGeneric.html。例如,

mathOps <- unlist(lapply( c("Arith","Compare","Math"), getGroupMembers ))
#  [1] "+"        "-"        "*"        "^"        "%%"       "%/%"     
#  [7] "/"        "=="       ">"        "<"        "!="       "<="      
# [13] ">="       "abs"      "sign"     "sqrt"     "ceiling"  "floor"   
# [19] "trunc"    "cummax"   "cummin"   "cumprod"  "cumsum"   "exp"     
# [25] "expm1"    "log"      "log10"    "log2"     "log1p"    "cos"     
# [31] "cosh"     "sin"      "sinh"     "tan"      "tanh"     "acos"    
# [37] "acosh"    "asin"     "asinh"    "atan"     "atanh"    "cospi"   
# [43] "sinpi"    "tanpi"    "gamma"    "lgamma"   "digamma"  "trigamma"

Step 2:将你的表达式分解为抽象语法树 https://en.wikipedia.org/wiki/Abstract_syntax_tree.

getAST <- function( ee ) 
    lapply( as.list(ee), function(x) `if`(is.call(x), getAST(x), x) )

# Example usage
getAST( quote(sin(x+5)) )
# [[1]]
# sin
# 
# [[2]]
# [[2]][[1]]
# `+`
# 
# [[2]][[2]]
# x
# 
# [[2]][[3]]
# [1] 5

Step 3:根据您对“有效性”的定义遍历 AST

checkFxn <- function( ast, validOps )
{
  ## Terminal nodes of an AST will not be lists
  ## Wrap them into a list of length 1 to keep the recursion flow
  if( !is.list(ast) ) ast <- list(ast)

  ## Operators must be called with one or more arguments
  if( as.character(ast[[1]]) %in% validOps )
    return( `if`(length(ast) < 2, FALSE,
                 all(sapply(ast[-1], checkFxn, validOps))) )

  ## Variables x and m are OK
  if( identical(ast[[1]], quote(x)) || identical(ast[[1]], quote(m)) )
    return(TRUE)

  ## Constants are OK
  if( is.numeric(ast[[1]]) ) return(TRUE)

  ## Everything else is invalid
  FALSE
}

把它们放在一起

exprs <- lapply( list(s1,s2,s3,s4), str2lang )   # Convert strings to expressions
asts <- lapply( exprs, getAST )                  # Build ASTs
sapply( asts, checkFxn, mathOps )                # Evaluate validity
# [1]  TRUE  TRUE FALSE FALSE 

AST 的替代品

正如@Moody_Mudskipper 所指出的,人们还可以使用all.names检索任意表达式中出现的符号列表。虽然这不会保留这些符号的相对结构,但可以直接将名称与mathOps.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

R - 使用非标准评估检查字符串是否是有效的数学表达式 的相关文章

  • 从每小时中提取/子集分钟值

    我的数据框包含以下格式的日期值YYYY MM DD HH MM SS跨越 125000 多行 按分钟细分 每行代表一分钟 1 2018 01 01 00 04 00 2 2018 01 01 00 05 00 3 2018 01 01 00
  • R:如何将描述小时、分钟和秒的非直观字符串转换为可行的 POSIXct 格式以执行标准算术?

    我在 R 中有一个数据集 其值采用小时 分钟和秒格式 然而 有些值只有小时和分钟 有些值只有分钟和秒 有些值只有分钟 有些值只有秒 它的格式也不是很有利 样本数据如下 example lt as data frame c 22h28m 17
  • r:按多列分组并计数

    我有以下数据框 df LeftOrRight SpeedCategory NumThruLanes R 25to45 3 L 45to62 2 R Gt62 1 我想按速度类别对其进行分组 并循环遍历其他列以获取每个速度类别中每个唯一代码的
  • 如何更改 r 中的树状图标签

    我在 R 中有一个树形图 它基于使用 hclust 的分层聚类 我正在对不同颜色的标签进行着色 但是当我尝试使用以下命令更改树图的标签 集群所基于的数据帧的行 时dendrogram dendrogram gt set labels dat
  • 在 R 中使用深度网络和 MNIST 数据读取手写数字第 3 部分

    我尝试编写一个基于深度网络的程序来读取手写数字 我在 Youtube 上找到了一个代码 https www youtube com watch v 5bso 5X7Zu4 https www youtube com watch v 5bso
  • data.table 的包装函数

    我有一个已经使用 data frame 上下文编写的项目 为了缩短计算时间 我尝试利用 data table 的速度 我的方法是构造包装函数 读取帧 将它们转换为表 进行计算 然后转换回帧 这是一个简单的例子 FastAgg lt func
  • 正则表达式提取美国邮政编码,但不提取假代码

    使用 XML 包和 XPath 从网站上抓取地址 有时我只能得到一个嵌入了我想要的邮政编码的字符串 提取邮政编码很简单 但有时会显示其他五位数字的字符串 以下是 df 中问题的一些变体 zips lt data frame id seq 1
  • XLConnect 无法确定 JAVA_HOME 错误

    感谢您的帮助 我正在尝试运行 XLconnect 但收到此错误消息 gt library XLConnect lib loc C Users 1144143929 Documents R win library 2 15 Error onL
  • 使用faceting()时如何连接geom_point()和geom_line?

    我有一个问题 但我在互联网上没有找到任何相关信息 我很高兴得到一些提示 我有一个数据集 其中 x 轴是离散的 但我想将这些点相互连接 我可以做到 我的问题是当我添加分面选项时 我无法再将这些点相互链接起来 我找到了一个替代方案 但看起来不太
  • 如何通过组度量的平均值在 df 内排列 dplyr:: 组?

    借鉴吴卡拉的设计https stackoverflow com a 26555424 9350837 https stackoverflow com a 26555424 9350837答案 我希望根据各个组汇总测量的平均值对分组 df 进
  • Shiny :针对所有错误显示一条消息

    我在 R 的 Shiny 中有一个应用程序 我想处理消息 以便用户看不到发生了什么错误 我知道通过 tags style type text css shiny output error visibility hidden shiny ou
  • 如何在R中创建for循环? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在 R 编程中启动 for 循环 https stackoverflow com questions 4162363 how to start a for loop in r programmin
  • 使用 R Markdown 文档作为函数源

    我正在研究 R Markdown 来记录我经常使用的功能 我会将它们放入 R Markdown 文件中以记录它们 然后如果我几个月后回来查看它 就能够阅读我在函数背后的想法 我的问题是 如果我开始一个新的 R 项目 是否可以获取 r mar
  • 如何创建 highcharter 事件函数以在 Shiny R 中创建“下拉函数”

    我正在建造一个shiny应用程序 我想要完成的事情之一是创建一个下拉菜单 我想将劳动力变量绘制为不同级别的年份变量的函数 请参阅下面的示例数据框 year level 2 level 3 labour 1 2013 10 101 1 2 2
  • R 无法回忆起内存中的对象

    我正在构建一个包含多个步骤的函数 其中每个步骤都会创建一个对象 某个步骤失败 temp3 并且无法找到前面的步骤对象 错误 未找到对象 temp2 我不知道为什么 我有类似的函数 遵循完全相同的结构 每个步骤都遵循先前创建的对象 在函数内
  • 构造奎因(自我复制功能)

    有没有人构建过 quine 生成自己源文本的副本作为其完整输出的程序 http www nyx net gthompso quine htm http www nyx net gthompso quine htm 在 R 中 quine 标
  • ggplot2 中的中心图标题

    这个简单的代码 以及今天早上我的所有脚本 已经开始在 ggplot2 中给我一个偏离中心的标题 Ubuntu version 16 04 R studio version Version 0 99 896 R version 3 3 2 G
  • 在列标题和配对变量中嵌入数据的数据透视表

    假设我有这样的数据 不幸的是 变量值嵌入在列名称中 library tidyr library dplyr dat lt tribble group var1 var meta1 var2 var meta2 group1 5 2 cat
  • 按名称包含在单个对象中的多个列对 data.frame 进行排序?

    我想排序一个data frame由多列组成 理想情况下使用基础 R 无需任何外部包 尽管如果有必要 就这样吧 读过如何按列对数据框进行排序 https stackoverflow com questions 1296646 how to s
  • 解压 R 数据框中的列表

    我有一个dataframe其中一个字段包含不同长度的列表 我想将该字段中列表的每个元素提取到其自己的字段中 以便我可以将结果收集到一个很长的字段中dataframe每个列表元素都有一个 id 这是一个例子dataframe dat lt s

随机推荐

  • 优化php中的大导入

    我有一个简单的导入器 它会遍历相当大的 csv 的每一行并将其导入到数据库中 我的问题是 我应该调用另一个方法来插入每个对象 生成 DO 并告诉它的映射器插入 还是应该在导入方法中对插入过程进行硬编码 复制代码 我知道最优雅的做法是调用第二
  • idea intellij maven项目无法make

    我有 Maven 项目 Maven 构建完成成功 但我无法完成这个项目 信息 取得成功 项目包含一个模块 Idea 看不到依赖关系 Error 3 38 java D Dropbox Programming java spring spri
  • Javascript垂直居中div(可变高度)

    我正在尝试使用 Javascript 将 div 垂直居中 因为文本会发生变化 所以我不能使用固定的高度 我想做这个without Jquery box2 width 100 height 100 position relative bac
  • UITableViewCells 初始加载视图/显示问题

    所以我有一个UITableView加载多列报价 进入后UITableView显示此数据时 单元格最初似乎未正确加载 文本看起来确实被压扁和 或被切断 大约 1 2 秒后 它正确加载 一切正常 每次加载表视图时都会发生这种情况 例如 这是一个
  • 使用 DateTime 列设置 LinqDataSourceWhere 子句

    在 C net 中 我有以下数据源设置 我试图在后面的代码中动态分配 WHERE 子句
  • MySQL:在已填充的表中创建新的唯一字段

    我需要在数据库表中创建一个已填充数据的字段 当然 仅仅将字段添加为空是不可能的 我只能想到创建一个新结构的新表 并将现有数据复制到新表中 但我想知道是否有更简单的方法 提示 它是一个复合键 由同一个表中的其他 3 个字段组成 编辑 该字段保
  • 提取 msi 时出现错误 2203

    我在使用以下命令提取 msi 时收到 2203 错误 msiexec a C Test Installer msi QB targetDIR C Test Eval LV C Test INST Logfile log 回答时请考虑以下几点
  • 使用相对路径时 VS10 附加库目录失败

    当我使用相对路径设置项目时 它失败了 不起作用 属性 链接器 常规 附加库目录 libraries 工作正常 C Users NAME Desktop project libraries 如何使相对路径发挥作用 尝试使其相对于您的项目目录或
  • 如何获取匹配 REGEX 后的文本

    我有字符串 我的家 和正则表达式 例如 reg hom 我正在努力找出如何在比赛后获取文本 直到单词结尾 在本例中我正在寻找 e 另一个例子 string soulful reg soul gt gt gt 我需要 完整 先感谢您 您可以使
  • GCC 内存屏障 __sync_synchronize 与 asm 易失性("": : :"内存")

    asm volatile memory 通常用作内存屏障 例如 如 Linux 内核中所示 barrier macro 这听起来类似于 GCC 内置的 sync synchronize http gcc gnu org onlinedocs
  • 气流错误:AttributeError:模块“airflow.utils.log”没有属性“file_processor_handler”

    我的本地气流即时已启动并正在运行 但现在当我运行气流网络服务器或任何其他气流命令时 我收到以下错误 带有一些回溯 Unable to load the config contains a configuration error Traceb
  • 通过代码向 Winforms DataGridView 添加新列

    我正在尝试为给定月份的每一天添加 N 列 var daysCount DateTime DaysInMonth DateTime Now Year month for int i 1 i lt daysCount i dataGridVie
  • 有条件地平均 DataTable 中的一列数据

    我有一个 DataTable 对象 dTable 其中所有 DataColumn 数据类型都是字符串或双精度 列中的某些数字不存在 即 空 现在我有下面的代码来查找平均值 并且当有值时它效果很好 var sum dTable AsEnume
  • 如何在没有流或系统 io 的情况下压缩字节数组

    我正在尝试将图像编码为字节数组并将其发送到服务器 编码和发送部分工作正常 但我的问题是字节数 组太大并且发送时间太长 所以我认为压缩它会让它运行得更快 但实际的问题是我不能使用 system io 或流 我的目标是 net 2 0 谢谢 u
  • 如何判断一个图是否有环?

    我知道这个问题在这个论坛和互联网上的其他地方已经被问过很多次了 但在你伸出爪子攻击我之前 请耐心等待 我是一个新手学习图 作为练习的一部分 我在此处的 Graph 类中添加了一个方法 has Cycle http homepage cs u
  • 当存在重复索引时,numpy 会保留分配顺序吗?

    我想通过索引数组对数组进行赋值 但存在重复的索引 例如 a np arange 5 index np array 1 2 3 1 2 3 1 2 3 b np arange 9 a index b 两个问题 对于重复索引 最新的分配总是生效
  • 对 NgRx 效果进行单元测试以确保服务方法被调用 - 不起作用

    我正在使用 NgRx 7 0 0 版本 这是我的 NgRx 效果类 import Injectable from angular core import ApisService from apis service import Effect
  • 将数据对象从父组件传递到子组件

    我正在列一个工具清单 我试图使用单个文件模板将完整的工具数据对象从父组件 工具列表 传递到每个子组件 工具项 在子组件中 我收到此错误 属性或方法 未在实例上定义 但在渲染期间引用 确保在数据选项中声明反应数据属性 Where 是工具数据对
  • Chrome 扩展选项卡从后台发送消息到内容脚本错误

    内容脚本 js chrome runtime onMessage addListener function request sender sendResponse console log sender tab from a content
  • R - 使用非标准评估检查字符串是否是有效的数学表达式

    我想检查下面的字符串是否是有效的数学表达式 s1 sin x s2 sin x m s3 sin s4 sin xm 我所说的 有效 是指该表达式是以下内容的组合 运算符 必须与变量或常量结合使用 变量x and or m 常数 根据这个定