詳解R語言中的表達(dá)式、數(shù)學(xué)公式、特殊符號(hào)
在R語言的繪圖函數(shù)中,如果文本參數(shù)是合法的R語言表達(dá)式,那么這個(gè)表達(dá)式就被用Tex類似的規(guī)則進(jìn)行文本格式化。
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語言的“表達(dá)式”
在R語言中,“表達(dá)式”的概念有狹義和廣義兩種意義。狹義的表達(dá)式指表達(dá)式(expression)類對(duì)象,由expression函數(shù)產(chǎn)生;而廣義的的表達(dá)式既包含expression類,也包含R“語言”類(language)。expression和language是R語言中兩種特殊數(shù)據(jù)類:
getClass(“expression”)
# Class "expression" [package "methods"] # No Slots, prototype of class "expression" # Extends: "vector"
getClass(“l(fā)anguage”)
# 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類是虛擬類,它包括我們熟悉的程序控制關(guān)鍵詞/符號(hào)和name、call 子類。
##二、產(chǎn)生“表達(dá)式”的函數(shù)
雖然我們?cè)赗終端鍵入的任何有效語句都是表達(dá)式,但這些表達(dá)式在輸入后即被求值(evaluate)了,獲得未經(jīng)求值的純粹“表達(dá)式”就要使用函數(shù)。下面我們從函數(shù)參數(shù)和返回值兩方面了解expression、quote、bquote和substitute這幾個(gè)常用函數(shù)。
####1、expression 函數(shù)
expression函數(shù)可以有一個(gè)或多個(gè)參數(shù),它把全部參數(shù)當(dāng)成一個(gè)列表,每個(gè)參數(shù)都被轉(zhuǎn)成一個(gè)表達(dá)式向量,所以它的返回值是表達(dá)式列表,每個(gè)元素都是表達(dá)式類型對(duì)象,返回值的長(zhǎng)度等于參數(shù)的個(gè)數(shù):
(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"
因?yàn)閑xpression函數(shù)把參數(shù)當(dāng)成列表處理,所以等號(hào)‘='兩邊的表達(dá)式要符合R語言列表元素的書寫規(guī)則,否則出錯(cuò),比如:
expression(x+11=1)
####2、quote函數(shù)
quote函數(shù)只能有一個(gè)參數(shù)。quote函數(shù)的返回值一般情況下是call類型,表達(dá)式參數(shù)是單個(gè)變量的話返回值就是name類型,如果是常量那么返回值的存儲(chǔ)模式就和相應(yīng)常量的模式相同:
(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或常量類型,它的長(zhǎng)度就是1;如果是call類型,返回值長(zhǎng)度就與函數(shù)/運(yùn)算符的參數(shù)個(gè)數(shù)n對(duì)應(yīng),長(zhǎng)度等于n+1,多出的長(zhǎng)度1是函數(shù)/符號(hào)名。
length(quote(a)) #name或常量類型,返回值長(zhǎng)度為1 ## [1] 1 length(quote(!a)) #單目運(yùn)算符,返回值長(zhǎng)度為2 ## [1] 2 length(quote(-b)) #單目運(yùn)算符,返回值長(zhǎng)度為2 ## [1] 2 length(quote(a + b)) #雙目運(yùn)算符,返回值長(zhǎng)度為3 ## [1] 3 length(quote((a + b) * c)) #多個(gè)運(yùn)算符只算優(yōu)先級(jí)最低的一個(gè) ## [1] 3
####3、bquote 和 substitute 函數(shù)
如果不使用環(huán)境變量或環(huán)境變量參數(shù),bquote 和 substitute 函數(shù)得到的結(jié)果與quote函數(shù)相同。
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 函數(shù)可以在表達(dá)式中使用變量,變量的值隨運(yùn)行進(jìn)程而被替換。bquote 和 substitute 函數(shù)變量替換的方式不一樣,bquote函數(shù)中需要替換的變量用 .( ) 引用,substitute函數(shù)中需要替換的變量用列表參數(shù)方式給出。除了這一點(diǎn),bquote 和 substitute 函數(shù)沒有差別:
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
搞出兩個(gè)功能完全一樣的函數(shù)不算很奇怪,R語言里面太多了,可能是照顧不同使用習(xí)慣的人們吧。bquote函數(shù)的幫助檔說這個(gè)函數(shù)類似于LISP的backquote宏,對(duì)于像我這樣的LISP盲,使用substitute函數(shù)好一些。 substitute函數(shù)的典型用途是替換表達(dá)式中的變量,如果我們希望在表達(dá)式中使用變量并且希望這些變量在運(yùn)行過程中做出相應(yīng)改變,就可以使用substitute函數(shù)。
par(mar = rep(0.1, 4), cex = 2) plot.new() 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 函數(shù)
parse函數(shù)用于從文件讀取文本作為表達(dá)式,返回的值是expression類型,這函數(shù)也很有用。后面有例子。
x <- 1 x + "x" ## Error: 二進(jìn)列運(yùn)算符中有非數(shù)值參數(shù) expression(x + "x") ## expression(x + "x") quote(x + "x") ## x + "x"
但R要檢查表達(dá)式中的運(yùn)算符,不符合運(yùn)算符使用規(guī)則的表達(dá)式將出錯(cuò):
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)
+ - 運(yùn)算連續(xù)使用不出錯(cuò)是因?yàn)樗鼈冞€可以當(dāng)成求正/負(fù)值運(yùn)算的符號(hào)。 在表達(dá)式產(chǎn)生函數(shù)中使用paste函數(shù)可以解決這樣的問題。在這種條件下,paste對(duì)參數(shù)的處理方式和表達(dá)式產(chǎn)生函數(shù)一樣,檢查運(yùn)算符但不檢查變量名。用NULL作為運(yùn)算符的參數(shù)可以獲得意外的效果:
ex <- expression(paste(x, "", y)) cl <- quote(paste(x, "****", y)) par(mar = rep(0.1, 4), cex = 2) plot.new() 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繪圖函數(shù)對(duì)文本參數(shù)中的表達(dá)式的處理
quote, bquote 和 substitute 的返回值有三種類型call, name 和 常量,事實(shí)上expression 函數(shù)的結(jié)果最終也是這三種類型。因?yàn)閑xpression函數(shù)的結(jié)果是expression列表,我們?nèi)×斜碓氐闹禉z查看看:
(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"
確實(shí)是這樣。所以繪圖函數(shù)對(duì)文本參數(shù)中的表達(dá)式處理就有三種情況。先看看處理結(jié)果:
par(mar = rep(0.1, 4), cex = 2) plot.new() 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 和常量類型都很簡(jiǎn)單,直接輸出文本,而call類型就不好判斷了。我們前面說過call類型返回值的長(zhǎng)度與函數(shù)/運(yùn)算符的參數(shù)個(gè)數(shù)有關(guān)。這是怎么體現(xiàn)的呢?由于文本參數(shù)最終得到的是文本,我們用as.character函數(shù)來看看:
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"
轉(zhuǎn)換成字符串向量后排在第一位的是運(yùn)算符或函數(shù)名稱,后面是參數(shù)(如果參數(shù)中還有運(yùn)算符或函數(shù)名,R還會(huì)對(duì)其進(jìn)行解析)。運(yùn)算符和函數(shù)是相同的處理方式。事實(shí)上,在R語言中,所有運(yùn)算符(包括數(shù)學(xué)運(yùn)算符和邏輯運(yùn)算符)都是函數(shù),你可以用函數(shù)的方式使用運(yùn)算符:
2 + 4 ## [1] 6 2 - 4 ## [1] -2 2 <= 4 ## [1] TRUE 2 >= 4 ## [1] FALSE
R繪圖函數(shù)對(duì)表達(dá)式中包含的函數(shù)名和它們的參數(shù)首先應(yīng)用Tex文本格式化規(guī)則進(jìn)行處理,這種規(guī)則的具體情況可以使用 ?plotmath 進(jìn)行查看,主要是一些數(shù)學(xué)公式和符號(hào)的表示方法。把這個(gè)說明文檔中字符串拷貝到maths.txt文件中并保存到當(dāng)前工作目錄后可以用下面的代碼做出后面的表格:
ex <- parse("maths.txt") labs <- readLines("maths.txt") n <- length(ex) par(mar = rep(0.1, 4), cex = 0.8) plot.new() 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 <- expand.grid(x, y) text(xy, labs, adj = c(0, 0.5)) xy <- expand.grid(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)
右鍵查看圖片,瀏覽大圖
表中奇數(shù)列是字符串(表達(dá)式),偶數(shù)列(藍(lán)色)是Tex格式化的圖形。除了上表列出的規(guī)則外還有一些拉丁文和希臘文符號(hào),可以在表達(dá)式中用 symbol 函數(shù)或名稱(如alpha)等表示,用到時(shí)自己去找吧。 如果函數(shù)名(包括運(yùn)算符)有對(duì)應(yīng)的Tex格式化規(guī)則,函數(shù)名和參數(shù)都按規(guī)則進(jìn)行圖形繪制;如果沒有,就當(dāng)成是R語言普通函數(shù):
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.new() 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種運(yùn)算函數(shù)都是有對(duì)應(yīng)數(shù)學(xué)符號(hào)的,所以它出的圖(符號(hào)和順序)與數(shù)學(xué)習(xí)慣一致,后三種運(yùn)算函數(shù)沒有對(duì)應(yīng)數(shù)學(xué)符號(hào),所以用普通函數(shù)方式(函數(shù)名在前,參數(shù)在括號(hào)內(nèi)用逗號(hào)分隔)出圖。其他還有一些瑣碎的規(guī)則,自己找找吧。
到此這篇關(guān)于詳解R語言中的表達(dá)式、數(shù)學(xué)公式、特殊符號(hào)的文章就介紹到這了,更多相關(guān)R語言表達(dá)式、數(shù)學(xué)公式、特殊符號(hào)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解決R語言中install_github中無法安裝遇到的問題
這篇文章主要介紹了解決R語言中install_github中無法安裝遇到的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04R語言-使用ifelse進(jìn)行數(shù)據(jù)分組
這篇文章主要介紹了R語言-使用ifelse進(jìn)行數(shù)據(jù)分組,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04Rcpp和RcppArmadillo創(chuàng)建R語言包的實(shí)現(xiàn)方式
這篇文章主要為大家介紹了Rcpp和RcppArmadillo創(chuàng)建R包實(shí)現(xiàn)方式,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11R語言 實(shí)現(xiàn)將factor轉(zhuǎn)換成numeric方法
這篇文章主要介紹了R語言 實(shí)現(xiàn)將factor轉(zhuǎn)換成numeric方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-03-03R語言時(shí)間序列知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理了一篇關(guān)于R語言時(shí)間序列知識(shí)點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-03-03R語言-實(shí)現(xiàn)按日期分組求皮爾森相關(guān)系數(shù)矩陣
這篇文章主要介紹了R語言-實(shí)現(xiàn)按日期分組求皮爾森相關(guān)系數(shù)矩陣,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-04-04