R處理資料小技巧:使用Non-standard evaluation來加速資料整理(函數quote,parse,assign,eval,expression)

在使用R處理資料的時候,很多時候會遇到文字型態的資料,他有表達某種運算或是簡化的觀念,這邊舉一個例子,比如一比標註藥物基因體資料內容如下:“CYP2C191-10”,對我們來說,可以理解成CYP2C191到CYP2C1910,總共十筆資料,這時候該如何用R處理呢?此時便可以使用Non-standard evaluation的觀念來處理,下面是範例,這邊會使用到quote,parse,eval等在處理此類問題的函數,其實Hadley Wickham正在開發一個用來處理Non-standard evaluation的工具包Lazyeval

基本上,quote, parse, eval這三個最基本的函數便可以演示一下所謂的non-standard evalution在做什麼,簡單說就是當syntax非正常console可接受語法的時候,該如何讓其繼續發揮功能!

那什麼是expression呢?
我們每個在R command line下所寫的算式或是函數的使用,其實就是一種expression,尤其是在像R這類非常interactive的程式語言,當我們輸入進去R console時候便是讓R去將expression執行出來,也就是去evaluation expression。正常在console下打1+1,按下輸入後,便會跑出2,但假如我們的輸入是“1+1”的字串呢?那麼這就必須使用non-standard evaluation來處理這類型的問題。

比如quote和expression這兩個函數可以用來包著這樣的表示

quote(1+1)
expression(1+1)

單這樣的話,代表用來處理尚未被evaluation的expression,這是後便用eval函數來執行這些expression:

eval(quote(1+1))
eval(expression(1+1))

screenshot.png

你也可以使用parse來將字串轉化為expression,那麼便可以執行,比如
screenshot.png

parse(text = "1+1")
eval(parse(text = "1+1"))
#處理基因變異資料的轉換,使用到non-standard evalution的觀念
"*3-*8, *11-*16, *19-*21" %>% str_split(",") %>%
                              unlist() %>%
                              str_replace_all("\\*","") %>%
                              str_replace_all("-",":") %>%
                              map(~parse(text=.)) %>%
                              lapply(eval) %>%
                              unlist %>%
                              as.character() %>%
                              str_replace_all("^","CYP2D6\\*")

另外,在處理這種將“text”轉變成為變數這件事上,assignget這兩個函數非常好用,可以放在expression處理這部上層,來解決一些複雜變數處理的問題。assign和get兩個函數的功能剛好相反,可以參考下面的範例

assign("A",c(1,2,3)
#> A
#> [1] 1 2 3
assign("A",data.frame(a=c(1,2),b=c(1,23)))
#> A
#> a b
#  1 1
#  2 23
get("A")
#> a b
#  1 1
#  2 23

相關閱讀參考:
Advance R:Non-standard evaluation

Non-standard-evaluation and standard evaluation in dplyr

Struggling with Non Standard Evaluation

Fun Standardizing Non Standard Evaluation

I hate non-standarad evalution

發表留言