这是对这个问题的跟进: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/