详解R语⾔中的表达式、数学公式、特殊符号⽬录
##⼀、R语⾔的“表达式”
##⼆、产⽣“表达式”的函数
####1、expression 函数
####2、quote函数
####3、bquote 和 substitute 函数
####4、parse 函数
##三、R绘图函数对⽂本参数中的表达式的处理
在R语⾔的绘图函数中,如果⽂本参数是合法的R语⾔表达式,那么这个表达式就被⽤Tex类似的规则进⾏⽂本格式化。
y <- function(x) (exp(-(x^2)/2))/sqrt(2*pi)
plot(y, -5, 5, main = expression(f(x) == frac(1,sqrt(2*pi))*e^(-frac(x^2,2))), lwd = 3, col = "blue")
library(ggplot2)
x <- seq(0, 2*pi, by = 0.01)
y <- sin(x)
data <- data.frame(x, y)
p <- ggplot(data, aes(x, y)) + geom_line()
p + geom_area(fill = 'blue', alpha = 0.3) +
scale_x_continuous(breaks = c(0, pi, 2*pi), labels = c('0', expression(pi), expression(2*pi))) +
geom_text(parse = T, aes(x = pi/2,y = 0.3, label = 'integral(sin(x)*dx, 0, pi)'))
##⼀、R语⾔的“表达式”
在R语⾔中,“表达式”的概念有狭义和⼴义两种意义。狭义的表达式指表达式(expression)类对象,由expression函数产⽣;⽽⼴义的的表达式既包含expression类,也包含R“语⾔”类(language)。expression和language是R语⾔中两种特殊数据类:
函数prototypegetClass(“expression”)
# Class "expression" [package "methods"]
# No Slots, prototype of class "expression"
# Extends: "vector"
getClass(“language”)
# Virtual Class "language" [package "methods"]
# No Slots, prototype of class "name"
# Known Subclasses:
# Class "name", directly
# Class "call", directly
# Class "{", directly
# Class "if", directly
# Class "<-", directly
# Class "for", directly
# Class "while", directly
# Class "repeat", directly
# Class "(", directly
# Class ".name", by class "name", distance 2, with explicit coerce
可以看到expression类由向量派⽣得到,⽽language类是虚拟类,它包括我们熟悉的程序控制关键词/符号和name、call ⼦类。
##⼆、产⽣“表达式”的函数
虽然我们在R终端键⼊的任何有效语句都是表达式,但这些表达式在输⼊后即被求值(evaluate)了,获得未经求值的纯粹“表达式”就要使⽤函数。下⾯我们从函数参数和返回值两⽅⾯了解expression、quote、bquote和substitute这⼏个常⽤函数。
####1、expression 函数
expression函数可以有⼀个或多个参数,它把全部参数当成⼀个列表,每个参数都被转成⼀个表达式向量,所以它的返回值是表达式列表,每个元素都是表达式类型对象,返回值的长度等于参数的个数:
(ex <- expression(x = 1, 1 + sqrt(a)))
## expression(x = 1, 1 + sqrt(a))
length(ex)
## [1] 2
ex[1]
## expression(x = 1)
mode(ex[1])
## [1] "expression"
typeof(ex[1])
## [1] "expression"
ex[2]
## expression(1 + sqrt(a))
mode(ex[2])
## [1] "expression"
typeof(ex[2])
## [1] "expression"
因为expression函数把参数当成列表处理,所以等号‘='两边的表达式要符合R语⾔列表元素的书写规则,否则出错,⽐如:
expression(x+11=1)
####2、quote函数
quote函数只能有⼀个参数。quote函数的返回值⼀般情况下是call类型,表达式参数是单个变量的话返回值就是name类型,如果是常量那么返回值的存储模式就和相应常量的模式相同:
(cl <- quote(1 + sqrt(a) + b^c))
## 1 + sqrt(a) + b^c
mode(cl)
## [1] "call"
typeof(cl)
## [1] "language"
(cl <- quote(a))
## a
mode(cl)
## [1] "name"
typeof(cl)
## [1] "symbol"
(cl <- quote(1))
## [1] 1
mode(cl)
## [1] "numeric"
typeof(cl)
## [1] "double"
quote返回值如果是name或常量类型,它的长度就是1;如果是call类型,返回值长度就与函数/运算符的参数个数n对应,长度等于n+1,多出的长度1是函数/符号名。
length(quote(a)) #name或常量类型,返回值长度为1
## [1] 1
length(quote(!a)) #单⽬运算符,返回值长度为2
## [1] 2
length(quote(-b)) #单⽬运算符,返回值长度为2
## [1] 2
length(quote(a + b)) #双⽬运算符,返回值长度为3
## [1] 3
length(quote((a + b) * c)) #多个运算符只算优先级最低的⼀个
## [1] 3
####3、bquote 和 substitute 函数
如果不使⽤环境变量或环境变量参数,bquote 和 substitute 函数得到的结果与quote函数相同。
bquote(1 + sqrt(a) + b^c) == quote(1 + sqrt(a) + b^c)
## [1] TRUE
substitute(1 + sqrt(a) + b^c) == quote(1 + sqrt(a) + b^c)
## [1] TRUE
但是bquote 和 substitute 函数可以在表达式中使⽤变量,变量的值随运⾏进程⽽被替换。bquote 和 substitute 函数变量替换的⽅式不⼀样,bquote函数中需要替换的变量⽤ .( ) 引⽤,substitute 函数中需要替换的变量⽤列表参数⽅式给出。除了这⼀点,bquote 和 substitute 函数没有差别:
a <- 3
b <- 2
(bq <- bquote(y == sqrt(.(a), .(b))))
## y == sqrt(3, 2)
(ss <- substitute(y == sqrt(a, b), list(a = 3, b = 2)))
## y == sqrt(3, 2)
bq == ss
## [1] TRUE
搞出两个功能完全⼀样的函数不算很奇怪,R语⾔⾥⾯太多了,可能是照顾不同使⽤习惯的⼈们吧。bquote函数的帮助档说这个函数类似于LISP的backquote宏,对于像我这样的LISP盲,使⽤substitute函数好⼀些。 substitute函数的典型⽤途是替换表达式中的变量,如果我们希望在表达式中使⽤变量并且希望这些变量在运⾏过程中做出相应改变,就可以使⽤substitute函数。
par(mar = rep(0.1, 4), cex = 2)
plot.window(c(0, 10), c(0, 1))
for (i in 1:9) text(i, 0.5, substitute(sqrt(x, a), list(a = i + 1)))
####4、parse 函数
parse函数⽤于从⽂件读取⽂本作为表达式,返回的值是expression类型,这函数也很有⽤。后⾯有例⼦。
x <- 1
x + "x"
## Error: ⼆进列运算符中有⾮数值参数
expression(x + "x")
## expression(x + "x")
quote(x + "x")
## x + "x"
但R要检查表达式中的运算符,不符合运算符使⽤规则的表达式将出错:
expression(x + +++y)
## expression(x + +++y)
expression(x - ---y)
## expression(x - ---y)
## expression(x****y) (Not run) expression(xy) (Not run)
## expression(1<=x<=4) (Not run)
quote(x + +++y)
## x + +++y
quote(x - ---y)
## x - ---y
## quote(x****y) (Not run) quote(xy) (Not run) quote(1<=x<=4) (Not run)
+ - 运算连续使⽤不出错是因为它们还可以当成求正/负值运算的符号。在表达式产⽣函数中使⽤paste函数可以解决这样的问题。在这种条件下,paste对参数的处理⽅式和表达式产⽣函数⼀样,检查运算符但不检查变量名。⽤NULL作为运算符的参数可以获得意外的效果:
ex <- expression(paste(x, "", y))
cl <- quote(paste(x, "****", y))
par(mar = rep(0.1, 4), cex = 2)
plot.window(c(0, 1.2), c(0, 1))
text(0.2, 0.5, ex)
text(0.6, 0.5, cl)
cl <- quote(paste(1 <= x, NULL <= 4))
text(1, 0.5, cl)
##三、R绘图函数对⽂本参数中的表达式的处理
quote, bquote 和 substitute 的返回值有三种类型call, name 和常量,事实上expression 函数的结果最终也是这三种类型。因为expression函数的结果是expression列表,我们取列表元素的值检查看看:
(ex <- expression(1 + sqrt(x), x, 1))
## expression(1 + sqrt(x), x, 1)
ex[[1]]
## 1 + sqrt(x)
mode(ex[[1]])
## [1] "call"
typeof(ex[[1]])
## [1] "language"
ex[[2]]
## x
mode(ex[[2]])
## [1] "name"
typeof(ex[[2]])
## [1] "symbol"
ex[[3]]
## [1] 1
mode(ex[[3]])
## [1] "numeric"
typeof(ex[[3]])
## [1] "double"
确实是这样。所以绘图函数对⽂本参数中的表达式处理就有三种情况。先看看处理结果:
par(mar = rep(0.1, 4), cex = 2)
plot.window(c(0, 1.2), c(0, 1))
text(0.2, 0.5, ex[1])
text(0.6, 0.5, ex[2])
text(1, 0.5, ex[3])
name 和常量类型都很简单,直接输出⽂本,⽽call类型就不好判断了。我们前⾯说过call类型返回值的长度与函数/运算符的参数个数有关。这是怎么体现的呢?由于⽂本参数最终得到的是⽂本,我们⽤as.character函数来看看:
as.character(quote(x - y))
## [1] "-" "x" "y"
as.character(quote(1 - x + y))
## [1] "+" "1 - x" "y"
as.character(quote((1 + x) * y))
## [1] "*" "(1 + x)" "y"
as.character(quote(!a))
## [1] "!" "a"
as.character(quote(sqrt(x)))
## [1] "sqrt" "x"
转换成字符串向量后排在第⼀位的是运算符或函数名称,后⾯是参数(如果参数中还有运算符或函数名,R还会对其进⾏解析)。运算符和函数是相同的处理⽅式。事实上,在R语⾔中,所有运算符(包括数学运算符和逻辑运算符)都是函数,你可以⽤函数的⽅式使⽤运算符:
2 + 4
## [1] 6
2 - 4
## [1] -2
2 <= 4
## [1] TRUE
2 >= 4
## [1] FALSE
R绘图函数对表达式中包含的函数名和它们的参数⾸先应⽤Tex⽂本格式化规则进⾏处理,这种规则的具体情况可以使⽤ ?plotmath 进⾏查看,主要是⼀些数学公式和符号的表⽰⽅法。把这个说明⽂档中字符串拷贝到⽂件中并保存到当前⼯作⽬录后可以⽤下⾯的代码做出后⾯的表格:
ex <- parse("")
labs <- readLines("")
n <- length(ex)
par(mar = rep(0.1, 4), cex = 0.8)
plot.window(c(0, 8), c(0, n/4))
y <- seq(n/4, by = -1, length = n/4)
x <- seq(0.1, by = 2, length = 4)
xy <- id(x, y)
text(xy, labs, adj = c(0, 0.5))
xy <- id(x + 1.3, y)
text(xy, ex, adj = c(0, 0.5), col = "blue")
box(lwd = 2)
abline(v = seq(1.3, by = 2, length = 4), lty = 3)
abline(v = seq(2, by = 2, length = 3), lwd = 1.5)
右键查看图⽚,浏览⼤图
表中奇数列是字符串(表达式),偶数列(蓝⾊)是Tex格式化的图形。除了上表列出的规则外还有⼀些拉丁⽂和希腊⽂符号,可以在表达式中⽤ symbol 函数或名称(如alpha)等表⽰,⽤到时⾃⼰去吧。如果函数名(包括运算符)有对应的Tex格式化规则,函数名和参数都按规则进⾏图形绘制;如果没有,就当成是R语⾔普通函数:
ex <- expression(sqrt(x), x + y, x^2, x %in% A, x <= y, mean(x, y, z), x | y, x & y)
n <- length(ex)
par(mar = rep(0.1, 4), cex = 1.5)
col <- c("red", "blue")
plot.window(c(0, n), c(0, 1))
for (i in 1:n) text(i - 0.5, 0.5, ex[i], col = col[i%%2 + 1])
上⾯例⼦中前5种运算函数都是有对应数学符号的,所以它出的图(符号和顺序)与数学习惯⼀致,后三种运算函数没有对应数学符号,所以⽤普通函数⽅式(函数名在前,参数在括号内⽤逗号分隔)出图。其他还有⼀些琐碎的规则,⾃⼰吧。
到此这篇关于详解R语⾔中的表达式、数学公式、特殊符号的⽂章就介绍到这了,更多相关R语⾔表达式、数学公式、特殊符号内容请搜索以前的⽂章或继续浏览下⾯的相关⽂章希望⼤家以后多多⽀持!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论