对数刻度上的闪亮滑块

时间:2015-05-28 09:42:57

标签: r slider shiny

我使用Shiny构建一个简单的Web应用程序,其中slider控制输出中应显示的p值。

如何使滑块以对数而不是线性的比例运行?

目前我有:

sliderInput("pvalue",
            "PValue:",
            min = 0,
            max = 1e-2,
            value = c(0, 1e-2)
),

谢谢!

5 个答案:

答案 0 :(得分:12)

我不确定你想要什么作为输出,但我所做的是可能的p值为[0,0.00001,0.0001,0.001,0.01]。如果你想要一些不同的东西,希望这个答案是一个很好的起点。

基本上,首先我创建了一个包含数字值(0,0.0000.1,...)的数组,然后我只使用滑块API中的特殊更新功能使这些值粘到滑块上。一旦你弄清楚如何使用滑块的API,这很简单。此外,由于某种原因,在RStudio内运行这看起来很奇怪,但在浏览器中它很好。另外,请注意我有5ms的延迟,因为我想确保在滑块初始化后运行。不是最干净的解决方案,可能有更好的方法,但它确实有效。

library(shiny)

JScode <-
  "$(function() {
    setTimeout(function(){
      var vals = [0];
      var powStart = 5;
      var powStop = 2;
      for (i = powStart; i >= powStop; i--) {
        var val = Math.pow(10, -i);
        val = parseFloat(val.toFixed(8));
        vals.push(val);
      }
      $('#pvalue').data('ionRangeSlider').update({'values':vals})
    }, 5)})"

runApp(shinyApp(
  ui = fluidPage(
    tags$head(tags$script(HTML(JScode))),

    sliderInput("pvalue",
                "PValue:",
                min = 0,
                max = 1e-2,
                value = c(0, 1e-2)
    )
  ),
  server = function(input, output, session) {
  }
))

答案 1 :(得分:11)

不确定这个帖子是否仍处于活动状态,但为了防止想要添加更通用的方式&#34; logifying&#34; inputSlider使用ionRangeSlider的prettify函数属性而不是覆盖值,其优点是你可以像往常一样定义inputSlider的min,max,step和default值,然后在Javascript端发生的所有变化都是显示的值(显示两个选项,一个用于数字输出,一个用于科学记数法):

library(shiny)

# logifySlider javascript function
JS.logify <-
"
// function to logify a sliderInput
function logifySlider (sliderId, sci = false) {
  if (sci) {
    // scientific style
    $('#'+sliderId).data('ionRangeSlider').update({
      'prettify': function (num) { return ('10<sup>'+num+'</sup>'); }
    })
  } else {
    // regular number style
    $('#'+sliderId).data('ionRangeSlider').update({
      'prettify': function (num) { return (Math.pow(10, num)); }
    })
  }
}"

# call logifySlider for each relevant sliderInput
JS.onload <-
"
// execute upon document loading
$(document).ready(function() {
  // wait a few ms to allow other scripts to execute
  setTimeout(function() {
    // include call for each slider
    logifySlider('log_slider', sci = false)
    logifySlider('log_slider2', sci = true)
  }, 5)})
"

ui <- fluidPage(
  tags$head(tags$script(HTML(JS.logify))),
  tags$head(tags$script(HTML(JS.onload))),

  sliderInput("log_slider", "Log Slider (numbers):",
              min = -5, max = 3, value = -4, step = 1),

  sliderInput("log_slider2", "Log Slider (sci. notation):",
              min = -5, max = 3, value = 1, step = 0.5),

  br(),

  textOutput("readout1"),
  textOutput("readout2")
)

server <- function(input, output, session) {
  output$readout1 <- reactive({
    paste0("Selected value (numbers): ", input$log_slider, " = ", 10^input$log_slider)
  })

  output$readout2 <- reactive({
    paste0("Selected value (sci. notation): ", input$log_slider2, " = ", 10^input$log_slider2)
  })
}

shinyApp(ui, server)

output

答案 2 :(得分:5)

更新(2018年5月):

现在可以通过shinyWidgets::sliderTextInput()控件实现。您可以指定自定义步骤(例如,对数间隔),滑块可以逐步执行。缺点是您需要指定每个步骤,而不是max和min,并让滑块计算步骤,但它适用于此类应用程序。

小例子:

library(shiny)
ui <- fluidPage(
  shinyWidgets::sliderTextInput("pvalue2","PValue:",
                            choices=c(0, 0.0001, 0.001, 0.01),
                            selected=0, grid = T)
)
server <- function(input, output) {}
shinyApp(ui, server)

答案 3 :(得分:0)

问题没有得到更多关注的原因是它难以回答。要做到提问者想要的东西,你必须编写javascript并将其注入网页。下面是我适用于将shiny滑块正确格式化为日期的代码。我还没有尝试将其修改为对数,因为我只学习了足够的javascript来修改这个脚本,然后立即将其从内存中删除,以便为更重要的事情腾出空间,比如块下的酒吧的季节性啤酒菜单。

安美居:

    output$selectUI <-
        renderUI(
            list(sliderInput(inputId = "target", label = "Date",
                                             min = 0, max = diff_months(targetEnd(),targetStart()) - 1,
                                             value = diff_months(targetEnd(),targetStart()) - 1,
                                             animate = animationOptions( loop = T)),
                     singleton(HTML(
                '
            <script type="text/javascript">
            $(document).ready(function() {
            var monthNames = [ "Jan.", "Feb.", "Mar.", "Apr.", "May", "June",
            "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec." ];
            var endDate = new Date(',
                year(Sys.Date()),',', month(Sys.Date())
                ,', 1);
            var slider = $("#dates").slider();
            var labels = slider.domNode.find(".jslider-label span");
            labels.eq(0).text("Jan., 1962");
            labels.eq(1).text([monthNames[endDate.getUTCMonth() +1], endDate.getUTCFullYear()].join(", "));
            // override the default "nice" function.
            slider.nice = function(value) {
alert("hi")
                var ref_date = new Date(1962, 1, 1);
                var slider_date = new Date(ref_date.setMonth(ref_date.getMonth() + value));
                return [monthNames[slider_date.getUTCMonth()], slider_date.getUTCFullYear()].join(", ");
            }

            $(slider).trigger("slidechange");
            })

    $(document).ready(function() {
                var monthNames = [ "Jan.", "Feb.", "Mar.", "Apr.", "May", "June",
                    "July", "Aug.", "Sept.", "Oct.", "Nov.", "Dec." ];
      var slider = $("#target").slider();
            var labels = slider.domNode.find(".jslider-label span");
          labels.eq(0).text([monthNames[', month(targetStart()) +1, '],', year(targetStart()), '].join(", "));
            labels.eq(1).text([monthNames[', month(targetEnd()) + 1, '], ', year(targetEnd()), '].join(", "));


      // override the default "nice" function.
      slider.nice = function(value) {
alert("hi")
        var ref_date = new Date(', year(targetStart()), ', ', month(targetStart()),',1 );
        // each slider step is 4 weeks, translating to 24 * 3600 * 1000 milliseconds
        var slider_date = new Date(ref_date.setMonth(ref_date.getMonth() + value - 1));

        return [monthNames[slider_date.getUTCMonth()],
                slider_date.getUTCFullYear()].join(", ");
      }

            $(slider).trigger("slidechange");
    })
  </script>
            ')
            )
        )
)

答案 4 :(得分:-1)

我此刻并不光彩,我已经扩大了范围,如果你尝试这样的话会发生什么:

sliderInput("pvalue",
            "PValue:",
            min = 1e-02,
            max = 1e+02,
            value = -10^seq(-2, 2)
),

你的帖子提到1e-2,我用过1e-02,我检查过如下

> 1e-2==1e-02
[1] TRUE