[問題] 繪圖時不直接使用變數名稱

作者: clsmbstu   2017-08-23 19:03:23
[問題類型]:
程式諮詢(我想用R 做某件事情,但是我不知道要怎麼用R 寫出來)
[軟體熟悉度]:
使用者(已經有用R 做過不少作品)
[問題敘述]:
在ggplot2、plotly、leaflet等繪圖套件中,
很常直接用變數的名稱去做aesthetic mapping,
但是一旦碰到迴圈或其它programming需求,
它反而很難一般化。
像是下列的ggplot2繪圖範例就有些結果上的差別。
我知道ggplot2套件中有aes_string提供較好的解決方案,
但是其它繪圖套件(例如plotly或leaflet)有類似的function嗎?
還是它們用non-standard evaluation時不會有問題?
這個問題困擾我滿久了,有沒有人願意分享一下經驗?
謝謝!
[程式範例]:
# 最一般的做法
ggplot(mtcars, aes(mpg, qsec)) + geom_point() + facet_grid(. ~ am)
# 利用aes_string function
ggplot(mtcars, aes_string("mpg", "qsec")) + geom_point() + facet_grid(. ~ am)
# 以下結果是錯誤的圖
# 用[]指定column
ggplot(mtcars, aes(mtcars[,1], mtcars[,7])) + geom_point() + facet_grid(. ~ am)
# Non-standard evaluation
ggplot(mtcars, aes(eval(parse(text = "mpg"), envir = mtcars),
eval(parse(text = "qsec"), envir = mtcars))) +
geom_point() +
facet_grid(. ~ am)
Stack Overflow相關解答:https://goo.gl/onbTcz
[關鍵字]:
Non-standard evaluation, aesthetic mapping
作者: celestialgod (天)   2017-08-23 19:22:00
aes_string 不方便的話,可以考慮wrapr....如果你還在想要用column slice方式畫圖,乾脆直接用原本R的繪圖.....不知道你說的一般化是什麼,輸入x,y然後繪圖嗎?
作者: clsmbstu   2017-08-23 19:49:00
一般化很好舉例啊,例如我要一個shiny app,可以讓使用者從vs和am選任一當facet,再任選兩個column畫散佈圖,aes還有aes_string,但就沒有facet_grid_string需要迴圈的例子也很常見,例如我要依第一行當facet、第二行為x、第三行起每個奇數行當y,每個存一張圖,用數列一下就解決了,偏偏ggplot2就不給這樣玩。
作者: celestialgod (天)   2017-08-23 19:57:00
facet_grid就用paste + as.formula迴圈就用names然後取column
作者: clsmbstu   2017-08-23 19:58:00
不懂為什麼想要用column slice就得回原本的R繪圖......
作者: celestialgod (天)   2017-08-23 19:58:00
我覺得是沒用R的思維去思考ggplot2的設計QQ因為只有原本R繪圖才能 plot(mtcars[,1], mtcars[,2lattice或是ggplot2都用data.frame概念去設計table型式資料才比較值觀兩個vector要做圖,要考慮長度問題、順序問題table就很值觀的,同一列就是pair
作者: clsmbstu   2017-08-23 20:00:00
我反而覺得是ggplot跟其它繪圖套件不友善...
作者: celestialgod (天)   2017-08-23 20:01:00
如果覺得R不友善,就換個工具吧 我覺得這樣最好
作者: clsmbstu   2017-08-23 20:02:00
既然背後都是non-standard evaluation,為什麼不開放直接給字串或index數字?反正我一開始都給定data frame了
作者: celestialgod (天)   2017-08-23 20:03:00
那為什麼你給data.frame,不用欄名 才奇怪吧
作者: clsmbstu   2017-08-23 20:05:00
我想用欄名啊,啊除了aes_string以外又不吃字串
作者: celestialgod (天)   2017-08-23 20:05:00
所以我上面跟你說用 formula跟取names做迴圈
作者: celestialgod (天)   2017-08-23 20:06:00
還有 formula != NSE...
作者: clsmbstu   2017-08-23 20:06:00
而且這裡你給的都只限ggplot,plot_ly function呢?
作者: clsmbstu   2017-08-23 20:50:00
我從來沒有說formula == NSE......aes的說明直接就寫了"aes uses non-standard evaluationto capture the variable names."以shiny的例子來說,以下操作就不可能直接實現:ggplot(mtcars,aes(input$a,input$b))+geom_point()+facet_grid(. ~ input$c)再來如果用到shiny,我也會想納入plot_ly、leaflet等互動性更高的套件,那我也只是好奇大家都怎麼解決。
作者: celestialgod (天)   2017-08-23 20:58:00
https://gist.github.com/jcheng5/3239667google一下有很多人做這類東西其他套件應該也同理
作者: clsmbstu   2017-08-24 08:59:00
自問自答:若是ggplot2,facet_grid和facet_wrap都支援字串輸入,但方式不同,可參考它們的"facets"參數說明若是plotly與leaflet,目前看起來可一律用paste和as.formula將拼湊起來的字串轉換後送給繪圖函數常用功能中能夠直接將names函數輸出結果放到繪圖中的,目前我看到的只有aes_string以及facet_wrap。另外補充說明:因為aes用的就是non-standard evaluation所以我上面程式範例中使用eval(parse())的方法,到加入geom_point()看起來結果都是對的,但只要一facet就會出問題,相關的討論之一我放在原文的連結中,主要還是因為ggplot2內部在繪圖時重新建的data frame會出錯,不過ggplot2並沒有針對這點寫警告訊息,所以需要自己小心。

Links booklink

Contact Us: admin [ a t ] ucptt.com