[问题] 绘图时不直接使用变量名称

楼主: 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