• R语言
  • 怎样让含有 shiny 元素的 flexdashboard 生成 html 文档?

Cloud2016
可是据我理解 crosstalk 是用来做筛选、过滤之类的功能的,而且用到筛选或过滤的框里还必须是共享数据里面的某个字段。或者你告诉我用 crosstalk 咋跟直方图联动起来?

    yuanfan 是的,shiny 无法像普通静态网页一样独立运行,它一定得有一个 R 进程来支撑(因为后端运算都得在 R 里面进行)。这个 R 进程可以是在服务器上(如果这个例子需要其他人远程访问),也可以在你本地的电脑上。包含 shiny 元素的 R Markdown 文档只能点绿色三角形运行,或者用 rmarkdown::run(),没有 Knit 图标可以点,也不能用 rmarkdown::render()

    Cloud2016 我不知道 echarts4r 是否支持 crosstalk,要是不支持的话恐怕 crosstalk 也帮不上忙。至少这个页面上没有列出 echarts4r:https://rstudio.github.io/crosstalk/widgets.html

      yihui
      echarts4r 不支持 crosstalk,我试过了。

      那么有没有别的路子,不直接用shiny,但是仅仅用selectInput()呢?因为我的初衷就是鼓捣一个可以调整宽度的直方图然后发给用户看。shiny 我刚接触,部署那块还没开始学,稍微看看都是针对.R文档的,没看见怎么把.Rmd怎么弄到服务器上面去的(PS.也可能是我对这个工具太陌生而看漏了)。

        yuanfan 最简单的路子就是把这个 .Rmd 文档部署到服务器上,跟部署 .R 文件没有什么本质区别。

        其次简单的路子是你根据你的 selectInput() 里预设的窗宽把所有的直方图预先画出来保存成图片,然后在 HTML 页面上用 <select> 元素的 JavaScript 事件来控制显示哪幅图。这倒是个不错的 JS 练习。我就是在 2007 年这样玩图片开始玩起 JS 来的。

          yihui
          明白了,我选最简单的路子。
          次简单的路子对我这个纯纯的新手来说,可能是一种蠢蠢的死法。有一次,我把 knit 生成的 html 文档不用浏览器打开,而是当做文本文件打开看,里面的 css / html 有很多元素或者参数设置我都没见过,但是感觉网上搜搜就能看明白,而 JavaScript 那些定义这那、返回这那的都看不明白。我觉得 css/html 很好入门,将来经过量的积累就能达成质的飞跃,但是 JavaScript 我还完全迷蒙,连量的积累阶段都还没摸到。

            yuanfan 可能是一种蠢蠢的死法

            十分钟写个例子(窃以为这个例子简短高能,值得收受西瓜贿赂,前面的反斜杠解释还不值),只是看一眼总不会死吧:

            ---
            title: "下拉菜单控制直方图的窗宽"
            output: html_document
            ---
            
            提供一个下拉菜单。
            
            ```{r, echo=FALSE}
            n_breaks = c(5, 10, 15, 20)
            shiny::selectInput(
                "n_breaks",
                label = "频数调整(等宽)",
                choices = n_breaks,
                selected = 5)
            ```
            
            预先画出所有的图,放在一个类名为 `hist-all` 的层中。
            
            ```{r, class.chunk='hist-all'}
            x = faithful$eruptions
            for (i in n_breaks) {
              hist(x, breaks = seq(min(x), max(x), length.out = i + 1),
                   main = paste('n = ', i))
            }
            ```
            
            但是先不要显示它们。
            
            ```{css}
            /* 默认隐藏所有图片 */
            .hist-all img { display: none; }
            /* 但图上如果加了 show 类就显示 */
            .hist-all .show { display: block; }
            ```
            
            召唤 JS 法力。
            
            ```{js}
            (d => {
              const s = d.getElementById('n_breaks'),  // 下拉菜单
                    imgs = d.querySelectorAll('.hist-all img');  // 图片元素数组
              
              // 按照 s 中被选中菜单项的下标 i 来向第 i 幅图添加类名“show”并移除其它图的类名
              function showImg() {
                const i = s.selectedIndex;
                imgs.forEach((el, k) => {
                  // k 为图片元素的下标,i 为选中菜单的下标,若二者相等则添加 show 类
                  el.classList.toggle('show', k == i); 
                });
              }
              
              // 小试牛刀,显示第一幅图
              showImg();
              
              // 当下拉菜单的值变动时(触发 onchange 事件),重新显示相应的图片
              s.onchange = showImg;
            })(document);
            ```

            这是个纯静态 HTML 页面,不需要部署到服务器,用 R Markdown 生成之后就可以脱离 R 运行。JS 代码中我用了相对较新的 => 语法,它是用来生成匿名函数的,x => {} 等价于 function(x) {};同理,(x, y) => {} 等价于 function(x, y) {}。最外面一层函数是为了避免创建全局对象、污染全局环境,而把所有对象都创建在一个匿名函数之内,最后再执行这个匿名函数(这是 JS 里最常见的伎俩),这伎俩 R 里面一样可以用(如 (function(x) {x + 1})(5))。除此之外,别的代码应该是不言自明的。

              yihui

              只是看一眼总不会死吧

              哈哈,《蠢蠢的死法》是一个游戏的名字。只看一眼当然不会狗带。西瓜和西红柿并不是贿赂,是表达感谢的心意。

              叫我写,就写不出来;看,能看明白。何况大神给每个步骤都写了详细的注释。但很奇怪的是我看到的代码,部分是蓝色的正体字,部分是黑色的斜体字。

                yuanfan 《蠢蠢的死法》是一个游戏的名字

                世上竟然有如此这般的游戏名字,本游戏盲真是死也不会想到。

                yuanfan 很奇怪的是我看到的代码,部分是蓝色的正体字,部分是黑色的斜体字。

                这是论坛 Markdown 程序的一个小问题,它蠢蠢地把一切下划线当做斜体语法了(n_breaks 里有个下划线,一直划过天际到下一个 n_breaks,真的是蠢到死)。