将主刻度标签设置为在R中的绘图中显示为科学符号

将主刻度标签设置为在R中的绘图中显示为科学符号,r,plotly,scientific-notation,R,Plotly,Scientific Notation,我正试图让绘声绘色地将值放入科学记数法中,而不管它们的大小,即100应该是刻度中的1E02,但它始终显示低于10.000的数字作为正常注释 设置格式是通过exponentformat=“E””完成的,但它只影响较大的数字 下面是我如何编写它的示例代码: f2 <- list(family = "Old Standard TT, serif", size = 14, color = "black") ax <- list(showticklabels = TRUE, tickfont

我正试图让
绘声绘色地
将值放入科学记数法中,而不管它们的大小,即100应该是刻度中的1E02,但它始终显示低于10.000的数字作为正常注释

设置格式是通过
exponentformat=“E”
”完成的,但它只影响较大的数字

下面是我如何编写它的示例代码:

f2 <- list(family = "Old Standard TT, serif", size = 14, color = "black")

ax <- list(showticklabels = TRUE, tickfont = f2,  showgrid=F,  zeroline=T,  showline=T,  nticks = 4,  exponentformat = "E")
ay <- list(nticks = 4,  showticklabels = TRUE,  tickfont = f2,  showgrid=F,  zeroline=T,  showline=T,  range =c(0,max(mtcars$disp*1.2)),  exponentformat = "E")

plot_ly(x = mtcars$mpg  , y = mtcars$disp) %>%
  add_trace(type = 'scatter', mode = 'markers', 
            marker = list(color = c('black'))) %>%
  add_lines(hoverinfo='none', line = list(color = 'black')) %>%
  layout(title = 'A plot in science',yaxis = ay, xaxis = ax,
         showlegend = FALSE, hovermode = "y")
f2%
布局(标题=‘科学中的情节’,yaxis=ay,xaxis=ax,
showlegend=FALSE,hovermode=“y”)
通过将值控制在10k+范围内,可获得所需的输出,但:

 mtcars$disp <- mtcars$disp *100 

mtcars$disp如果Plotly没有提供所需的功能,我们就用JavaScript自己动手吧

  • 让我们使用d3抓取y轴上的所有刻度

    ticks = Plotly.d3.selectAll('g.ytick');
    
  • 原始数据存储在
    data.x

  • 然后将每个符号的表示形式改为科学符号

    Plotly.d3
          .selectAll('g.ytick')
          .each(function(data, i) 
            {
               Plotly.d3.select(this)
                        .select('text')
                        .html(formatNumber(data.x, 2));
            }) 
    
    • 最后,在图中使用
      htmlwidgets
      注入所有代码


      p特别针对使用对数刻度的绘图(这似乎会导致当前javascript解决方案出现问题),我找到了另一个不使用
      javascript
      的解决方案。它的工作原理是:在整个指数上列出tickvalue和一个文本标签,其余的为空,然后通过
      layout
      参数
      tickvals
      ticktext
      参数将这两个标签插入到绘图中

      根据是常规的
      散点
      还是
      散点3D
      布局代码会有一些变化,但原理是一样的

      scatter3d
      中,轴在
      scene=list()
      参数中设置。在
      scatter
      中,轴直接在
      layout()
      中设置;
      自动调整大小
      等参数用于使打印美观、方正,用于右缩放级别的3D,且大小固定

      答案基于另一个SO帖子:

      库(闪亮)
      图书馆(绘本)
      shinyApp(
      ui=fluidPage(plotlyOutput(“plot”),
      服务器=功能(输入、输出){
      输出$plot 0])),数字=0)+1#确定所需的最大日志
      minlog 0],mtcars[['disp']][mtcars[['disp']]>0],mtcars[['cyl']]][mtcars[['cyl']]>0]),数字=0)-1#确定所需的最小日志
      
      logrange如何
      mtcars$disp我不认为这会有帮助,它可能应该在绘图的
      布局或
      标签中更改。在多面板绘图中,它似乎对我的数据做了非常奇怪的事情。绘图的数据是不同的行,并且当我应用格式方法时,范围参数也会失败th
      ggplot2
      ggplotly
      。嘿,max再次感谢您提供了另一个伟大的解决方案。2件事;这可以调整为使指数显示1或2位小数吗?第二件事是:我尝试将此应用于子图结构,在每个子图和整个图上都应用onrender,但在最好的情况下,它只影响第一个面板。我将为此发布一个新问题。这段代码对Plotly的刻度线(显示为10k和20k等)有着迷人的作用。请参见注释其他问题。它可以理解地将它们转换为1.00E1。Max,还有一点,我终于回到这个问题上了。您能演示如何一次性将其应用于x轴和y轴吗?@maximillian,谢谢。我刚刚发现了另一个障碍,当前的答案与plotly的布局(p,yaxis=list(type='log'))相结合,造成了可怕的混乱。我应该为这个特定场景写另一个问题吗?
      el.on('plotly_afterplot', fix_ticks);
      
      function formatNumber(num, desiredLength)
      {
        num = num.toExponential().toUpperCase();
        var r = /(\\d*)([E][-+])(\\d*)/;
        var fields = r.exec(num);
        if (fields !== null && fields.length > 3)
        {
          return fields[1] + fields[2] + fields[3].padStart(desiredLength, '0');
        }
        else
        {
          return num;
        }   
      }
      
      ticks.forEach(function(tick) 
      {
        var num = parseInt(tick[0].innerHTML); 
        tick[0].innerHTML = formatNumber(num, 2);
      })
      
      library(plotly)
      library(htmlwidgets)
      
      p <- plot_ly(x = mtcars$mpg  , y = mtcars$disp) %>%
        add_lines()
      
      javascript <- "
      function(el, x) 
      {
        function fixTicks()
        {
      
          Plotly.d3
                .selectAll('g.ytick')
                .each(function(data, i) 
                  {
                     Plotly.d3.select(this)
                              .select('text')
                              .html(formatNumber(data.x, 2));
                  }) 
        }
      
        function formatNumber(num, desiredLength)
        {
          num = num.toExponential().toUpperCase();
          var r = /(\\d*)([E][-+])(\\d*)/;
          var fields = r.exec(num);
          if (fields !== null && fields.length > 3)
          {
            return fields[1] + fields[2] + fields[3].padStart(desiredLength, '0');
          }
          else
          {
            return num;
          }
        }
      
        el.on('plotly_afterplot', fixTicks);
      }"
      
      p <- onRender(p, javascript)  
      p
      
          library(shiny)
          library(plotly)
      
          shinyApp(
            ui = fluidPage( plotlyOutput('plot') ),
      
            server = function(input, output) {
              output$plot <- renderPlotly ({
      
                mtcars <- rbind(mtcars, mtcars*1000, mtcars/1000)  #create data with big logarithmic range
                maxlog <- round(log10(max(mtcars[['mpg']][mtcars[['mpg']]>0], mtcars[['disp']][mtcars[['disp']]>0],mtcars[['cyl']][mtcars[['cyl']]>0])), digits = 0) +1 # determine max log needed
                minlog <- round(log10(min(mtcars[['mpg']][mtcars[['mpg']]>0], mtcars[['disp']][mtcars[['disp']]>0],mtcars[['cyl']][mtcars[['cyl']]>0])), digits = 0) -1 # determine min log needed
                logrange <- (maxlog - minlog)*9 +1 # get the distance between smallest and largest log power
                tval <- sort(as.vector(sapply(seq(1,9), function(x) x*10^seq(minlog, maxlog)))) #generates a sequence of numbers in logarithmic divisions
                ttxt <- rep("",length(tval))  # no label at most of the ticks
                ttxt[seq(1,logrange,9)] <- formatC(tval, format = "e", digits = 2)[seq(1,logrange,9)] # every 9th tick is labelled
      
      
                p <- plot_ly(source = 'ThresholdScatter')
                p <- add_trace(p, data = mtcars, 
                            x = mtcars[['mpg']], 
                            y = mtcars[['disp']],
                            z = mtcars[['cyl']],
                            type = 'scatter3d', 
                            mode = 'markers',
                            marker = list(size = 2)) 
      
            p <- layout(p, autosize = F, width = 500, height = 500,
                        scene = list(yaxis = list(type="log",
                                                  zeroline=F, showline=T, 
                                                  ticks="outside",
                                                  tickvals=tval,
                                                  ticktext=ttxt),
                                     xaxis = list(type="log",
                                                  zeroline=F, showline=T, 
                                                  ticks="outside",
                                                  tickvals=tval,
                                                  ticktext=ttxt),
                                     zaxis = list(type="log",
                                                  zeroline=F, showline=T, 
                                                  ticks="outside",
                                                  tickvals=tval,
                                                  ticktext=ttxt),
                                     camera = list(eye = list(x = -1.5, y = 1.5, z = 1.5))))
          })
        }
          )
      
      library(shiny)
      library(plotly)
      
      shinyApp(
        ui = fluidPage( plotlyOutput('plot') ),
      
        server = function(input, output) {
          output$plot <- renderPlotly ({
      
            mtcars <- rbind(mtcars, mtcars*1000, mtcars/1000)  #create data with big logarithmic range
            maxlog <- round(log10(max(mtcars[['mpg']][mtcars[['mpg']]>0], mtcars[['disp']][mtcars[['disp']]>0])), digits = 0) +1 # determine max log needed
            minlog <- round(log10(min(mtcars[['mpg']][mtcars[['mpg']]>0], mtcars[['disp']][mtcars[['disp']]>0])), digits = 0) -1 # determine min log needed
            logrange <- (maxlog - minlog)*9 +1 # get the distance between smallest and largest log power
            tval <- sort(as.vector(sapply(seq(1,9), function(x) x*10^seq(minlog, maxlog)))) #generates a sequence of numbers in logarithmic divisions
            ttxt <- rep("",length(tval))  # no label at most of the ticks
            ttxt[seq(1,logrange,9)] <- formatC(tval, format = "e", digits = 2)[seq(1,logrange,9)] # every 9th tick is labelled
      
      
            p <- plot_ly(source = 'ThresholdScatter')
            p <- add_trace(p, data = mtcars, 
                           x = mtcars[['mpg']], 
                           y = mtcars[['disp']],
                           type = 'scatter', 
                           mode = 'markers',
                           marker = list(size = 2)) 
      
            p <- layout(p,autosize = F, width = 500, height = 500,
                        yaxis = list(type="log",
                                       zeroline=F, showline=T, 
                                       ticks="outside",
                                       tickvals=tval,
                                       ticktext=ttxt),
                        xaxis = list(type="log",
                                     zeroline=F, showline=T, 
                                     ticks="outside",
                                     tickvals=tval,
                                     ticktext=ttxt))
          })
        }
      )