绘图轴为指数格式 [英] Plotly axis as exponential format
问题描述
This is a follow up on this question: SO Q
上述问题的答案使用JavaScript代码将轴刻度线变成指数.它适用于单个图上的单个轴.
The answer in the above question uses JavaScript code that turns an axis ticks into exponential. It works for a single axis on a single plot.
当在subplot()结构中运行它时,仅当我将其应用于最终图时,它才可在第一个图上使用.
When running it in a subplot() structure, it only works on the first plot when I apply it to the final plot.
我正在寻找的修改是:
1:如何使其在子图上工作.我尝试在每个子图的构建中调用JavaScript,但是所有图出都没有指数级.
1: How to make it work on subplots. I tried calling JavaScript in the build of each subplot, but all plots came out without exponential then.
2:使其在x和y轴上都可以工作(我尝试过,失败了,哭了一点)
2: make it work for both x an y axis (I tried, failed and cried a little)
3:当轴证明不是数字时,不要破坏宇宙(我的应用程序也可以绘制日期列,因此需要检查它是否实际上是数字输入)
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)
4:如果可能,打印为1.23E + 1而不是1E + 1
4: If possible print as 1.23E+1 rather than 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)
更新 有了这里给出的答案建议,我现在运行以下代码,检查数字,然后在每个轴上工作.我尚未获得使用负值[0] .innerHTML处理最后一个负值的建议.我最终在第1点的答案下使用了建议,因为我无法在tickt0循环中使用tick [0] .innerHTML方法.但是,针对早期评论的建议可以追溯到tick [0]方法,而我无法获得一种完全可行的方法.
UPDATE with the answer suggestions given here I am now running the following code that checks for numerical and then works for each axis. I haven't been able to get the last suggestion to deal with negative values to work yet, which was using tick[0].innerHTML. I ended up using the suggestion under the answer under point 1, using, as I could not get the tick[0].innerHTML approach to work inside the forEach loop. However, the suggestion in response to earlier comment is going back to the tick[0] approach, and I can't get one approach to work completely.
这是我在遇到负面-> NaN问题之前最终使用的代码
This is the code I ended up using before running into negative -> NaN problems
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:如何使其在子图上工作.我尝试在构建中调用Java 每个子图,但是所有图都没有指数化.
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.
第2/3rd/等的滴答声.子图具有类似y2tick
/y3tick
/etc的类名.我们可以降低d3选择器的特定性,然后使用each
更改所有刻度.
The ticks of the 2nd/3rd/etc. subplot have class names like y2tick
/y3tick
/etc. We could make our d3 selector less specific and then use each
to change all ticks.
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:使其在x和y轴上均有效(我尝试过,失败并哭了 小)
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')
Just change the selectAll statement to Plotly.d3.selectAll('g.xaxislayer-above').selectAll('text')
3:当轴转为不存在时,使其不破坏宇宙 数字(我的应用程序也可以绘制日期列,因此需要检查 是否实际上是数字输入)
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等值时,可能会比较棘手,您需要手动对其进行处理.
You could change your fixTicks
functions to check if the input value is numeric, e.g. by using typeof
or a regex. With values like 1999, 2000, etc. it might be tricky and you would need to manually address it.
4:如果可能,打印为1.23E + 1而不是1E + 1
4: If possible print as 1.23E+1 rather than 1E+1
toExponential
采用一个参数,即小数点后的符号",即num.toExponential(3)
可以解决您的问题.
toExponential
takes one parameter which is the "number of digits in the notation after the decimal point", i.e. num.toExponential(3)
would do the trick in your case.
根据评论:当价格变动值为负值时,我似乎会得到NaN
From the comment: I seem to get NaN when the values on the ticks are negative values
使用 Unicode减号代替常规破折号.您可以将其替换为以下JavaScript行:
Plotly uses an Unicode minus sign instead of a regular dash. You can replace it with the following JavaScript line:
var num = parseInt(tick[0].innerHTML.replace(/\\u2013|\\u2014|\\u2212/g, '-'));
注意:R中需要双反斜杠\\
,纯JavaScript只需一个\
.
Note: the double backslash \\
is required in R, pure JavaScript would require only a single \
.
这篇关于绘图轴为指数格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!