2020年2月27日 星期四

R 語言中的expression 一些用法

什麼是 Expression

先分別從數學和程式語言兩個定義來看待 expression

數學上的 expression

數學上 的 expression ,就是將一些數學符號排列在一起。可以是數字(number),也可以是運算子(operator)或符號(symbol)

用一個 x + 12 來說明 expression 的組成的話,x 是符號、 + 是運算子 、12 是數字

程式語言 expression

程式的expression 基本上和數學定義是差不多的,由運算子(operator)和運算元(operand)組成,比較明顯的差異在於程式的目的是要經過電腦算出結果。一般的情況下電腦中的expression會算出一個新的值,我們可以把這個值再賦值給一個變數

x <- 12 + 5

這個語法讓變數 x 被賦予了新的值

x + 1
## [1] 18

這個語法讓x被加法操作出現了新的值,差別在於沒有將這個值賦予到一個變數上

為了不要和數學混在一起,R語言的Expression 就先稱為 R expression

Expression Evaluation

接下來講到 evaluate

前面講到一般情況下R expression會算出一個新的值,因此也存在非一般的情況。R 語言有兩個特殊的 function,分別是 quote() 和 substitute()。這兩個function 都可以將R expression 卡住,使其保留在一個沒有被運算的狀態,直到被求值(evaluate) 後才開始運算

而這個「卡住」的狀態又可以經由 eval() 來重新算出來,這就是 evaluate

quote() ,expression() and substitute()

下面來整理一些 R expression 概念下常見的 function

quote()

最簡單的形式,其本質是類似list 的一種結構

c1<-quote(x+5)
c1[[1]]
## `+`
c1[[2]]
## x
c1[[3]]
## [1] 5

expression()

expression() 可以放入不止一個的R expression

update <- expression(
    x<-x +1, msg<-paste0("x=",x), print(msg))
x<-3
for(i in 1:5)eval(update)
## [1] "x=4"
## [1] "x=5"
## [1] "x=6"
## [1] "x=7"
## [1] "x=8"

substitute()

substitute 可以把 expression 設定好的變數 用list 的方式給予,所以會有這種操作

plot(0,type="n")
for (i in 1:4)
    text(1, 0.2 * i,
      substitute(x[ix] == y, list(ix = i, y = pnorm(i))))

plotmath

這大概是 expression 最常見的用途

plot(1:10, type="n", xlab="", ylab="", main = "plot math & numbers")
text(4, 9, expression(hat(beta) == (X^t * X)^{-1} * X^t * y))
text(4, 8.4, "expression(hat(beta) == (X^t * X)^{-1} * X^t * y)",
     cex = .8)
text(4, 7, expression(bar(x) == sum(frac(x[i], n), i==1, n)))
text(4, 6.4, "expression(bar(x) == sum(frac(x[i], n), i==1, n))",
     cex = .8)
text(8, 5, expression(paste(frac(1, sigma*sqrt(2*pi)), " ",
                            plain(e)^{frac(-(x-mu)^2, 2*sigma^2)})),
     cex = 1.2)

Derivatives

主要還是拿來算 gradient

ex1<-quote(1+5*x-x^2)
ex2<-deriv(ex1,'x')
D(ex1,'x')
## 5 - 2 * x
x<-2
fx<-eval(ex2)
fdx<-.grad[1,]
fdx
## x 
## 1

Non-standard evaluation

一種特殊的技巧

data(iris)
for(n in names(iris)){
    print(paste0(n," = head(iris$",n,")"))
    ex1<-parse(text=paste0(n," = head(iris$",n,")"))
    eval(ex1)
}
## [1] "Sepal.Length = head(iris$Sepal.Length)"
## [1] "Sepal.Width = head(iris$Sepal.Width)"
## [1] "Petal.Length = head(iris$Petal.Length)"
## [1] "Petal.Width = head(iris$Petal.Width)"
## [1] "Species = head(iris$Species)"
Petal.Width
## [1] 0.2 0.2 0.2 0.2 0.2 0.4
Species
## [1] setosa setosa setosa setosa setosa setosa
## Levels: setosa versicolor virginica

使用LibreOffice製作代碼瀑布

Matrix_Digital_Rain_in_Excel_1 Matrix Digital Rain in LibreOffice 之前在facebook 看到一個沒有見過的效果,一時興起就研究了一下 如何使用LibreOffie...