javascript - 以指数格式绘制轴

标签 javascript r plotly subplot

这是对这个问题的跟进:SO Q

上述问题的答案使用 JavaScript 代码将轴刻度转换为指数。它适用于单个绘图上的单个轴。

在 subplot() 结构中运行它时,当我将它应用到最终图时,它仅适用于第一个图。

我正在寻找的修改是这些:

1:如何让它在子图中起作用。我尝试在每个子图的构建中调用 JavaScript,但是所有的图都没有指数增长。

2:让它同时适用于 x 和 y 轴(我尝试过,失败了,哭了一点)

3: 让它在轴不是数字时不破坏宇宙(我的应用程序也可以绘制日期列,所以它需要检查它是否真的是一个数字输入)

4:如果可能打印为 1.23E+1 而不是 1E+1

 library(shiny)
library(plotly)
library(htmlwidgets)


ui <- fluidPage(
    mainPanel(
     plotlyOutput('myplotly')
     )
  )

server <- function(input, output, session) {

  javascript <- "
function(el, x) 
{
  function fix_ticks()
  {
    ticks = Plotly.d3.selectAll('g.ytick').selectAll('text');
    ticks.forEach(function(tick) 
    {
      var num = parseInt(tick[0].innerHTML); 
      tick[0].innerHTML = num.toExponential();
    })
  }
  el.on('plotly_afterplot', fix_ticks);
}"


  output$myplotly <- renderPlotly({

    myplots <- lapply(unique(mtcars$cyl), function(v) {

    data <- mtcars[which(mtcars$cyl == v), ] 
      subp <-   plot_ly(data = data,
                x = rownames(data), 
                y = ~mpg,
                type = "bar")
      subp
     })

    p <- subplot(myplots, margin = 0.08)

    p$elementId <- NULL   ## to surpress warning of widgetid
    p <- onRender(p, javascript)

    p <- p %>% layout(margin =list(l = 60, r = 20, b = 160, t = 70) )

    p
  })
 }

shinyApp(ui = ui, server = server)

更新 有了这里给出的答案建议,我现在正在运行以下代码来检查数值,然后为每个轴工作。我还没有得到最后一个处理负值的建议,它使用的是 tick[0].innerHTML。我最终使用了第 1 点答案下的建议,因为我无法让 tick[0].innerHTML 方法在 forEach 循环内工作。但是,针对早期评论的建议是回到 tick[0] 方法,我无法让一种方法完全起作用。

这是我在遇到负面 -> NaN 问题之前最终使用的代码

  javascriptMPP <- "
  function(el, x) 
  {
    function isNumber(n) {
      return (Object.prototype.toString.call(n) === '[object Number]' || Object.prototype.toString.call(n) === '[object String]') &&!isNaN(parseFloat(n)) && isFinite(n.toString().replace(/^-/, ''));
    }
    function fixTicks()
    {
      ticks = Plotly.d3.selectAll('g.yaxislayer-above,g.xaxislayer-above').selectAll('text');
      ticks.each(function(d) 
      {
        if(parseInt(d.text) !== 0 )
        {
          var num = parseInt(d.text).toExponential(2);
          Plotly.d3.select(this).text(num);
        }
      })
    }
    el.on('plotly_afterplot', fixTicks);
  }"

最佳答案

1: How to make it work on subplots. I tried calling java in the build of each subplot, but all plots came out without exponential then.

第二个/第三个/等的滴答声。子图的类名如 y2tick/y3tick/etc。我们可以让我们的 d3 选择器不那么具体,然后使用 each 来改变所有的刻度。

ticks = Plotly.d3.selectAll('g.yaxislayer-above').selectAll('text');
ticks.each(function(d, i) 
{
  var num = parseInt(d.text).toExponential();
  Plotly.d3.select(this).text(num);
})

2: make it work for both x an y axis (I tried, failed and cried a little)

只需将 selectAll 语句更改为 Plotly.d3.selectAll('g.xaxislayer-above').selectAll('text')

3: Make it not destroy the universe when the axis turns out to not be a numerical (My app can plot date columns too, so it needs to check whether it actually is a numerical input)

您可以更改 fixTicks 函数来检查输入值是否为数字,例如通过使用 typeof 或正则表达式。对于 1999、2000 等值,这可能会很棘手,您需要手动解决它。

4: If possible print as 1.23E+1 rather than 1E+1

toExponential 需要一个 parameter这是“小数点后符号中的位数”,即 num.toExponential(3) 可以解决您的问题。

From the comment: I seem to get NaN when the values on the ticks are negative values

Plotly 使用 Unicode minus sign而不是常规破折号。您可以将其替换为以下 JavaScript 行:

var num = parseInt(tick[0].innerHTML.replace(/\\u2013|\\u2014|\\u2212/g, '-'));

注意:双反斜杠 \\ 在 R 中是必需的,纯 JavaScript 只需要一个 \

关于javascript - 以指数格式绘制轴,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49818203/

相关文章:

在R中同时替换同一字符串的多个子字符串

r - 如何将 ggplot 对象向量传递给 grid.arrange 函数?

R plotly : Add segment on Boxplot plotly

javascript - 拉动刷新数据重复

javascript - 如何向 AJAX 提交动态生成的表单?

r - 带有砝码的快速标准偏差

python - plotly 尖峰未出现在次要 plotly 上

javascript - 如果 ajax 和 codeigniter 表单验证出现登录错误,则停止引导下拉菜单关闭

javascript - 使用下拉菜单启用/禁用日期选择器 asp.net

r - 如何在 R 中的 3d 散点图上将 Plotly 中的轴居中?