Adjust the decimals in scientific notation with Plots.jl

Hello!
I try to publish my figures so I need to edit them as nicely as possible.
I have trouble adjusting the format of my ylabel.

I would like to keep a scientific notation, but Plots.jl is automatically set to a two digits precision.
I would like to keep it to one (else, it takes too much place in subplots).

For example :

using Plots
x = 0:1:10
plot(x, x*1e-6)

How can I keep the ylabel with a format like 2.5x10^-6 instead of 2.50x10^-6 ?

I guess I should use yformatter, but I could not find a documentation or a tutorial to apply.
(I also take recommendations of backends for publication-grade figures)
Thanks!

1 Like

There are some examples here in discourse. See if this one helps.

With the latest recommended Format.jl package, try:

using Format, Plots
x = 0:1:10
plot(x, x*1e-6, yformatter = x -> cfmt( "%.1e", x), tickfontsize=6)
1 Like
1 dependency successfully precompiled in 1 seconds. 537 already precompiled.
  1 dependency had output during precompilation:
β”Œ Formatting
β”‚  β”Œ Warning: DEPRECATION NOTICE
β”‚  β”‚ 
β”‚  β”‚ Formatting.jl has been unmaintained for a while, with some serious
β”‚  β”‚ correctness bugs compromising the original purpose of the package. As a result,
β”‚  β”‚ it has been deprecated - consider using an alternative, such as
β”‚  β”‚ `Format.jl` (https://github.com/JuliaString/Format.jl) or the `Printf` stdlib directly.
β”‚  β”‚ 
β”‚  β”‚ If you are not using Formatting.jl as a direct dependency, please consider
β”‚  β”‚ opening an issue on any packages you are using that do use it as a dependency.
β”‚  β”‚ From Julia 1.9 onwards, you can query `]why Formatting` to figure out which
β”‚  β”‚ package originally brings it in as a dependency.
β”‚  β”” @ Formatting ~/.julia/packages/Formatting/3VxOt/src/Formatting.jl:12
β””  

I will try to see what Format.jl can do…

Please refer to the example I have added above.

I would prefer a notation with x10^n if it is not too hard.

I don’t know of an easy way, but the following is within reach, with some more labour:

using Plots

x = 0:1:10
p = plot(x, x*1e-6, yformatter=:scientific)
yt = yticks(p)
# Edit yt programmatically (done here manually):
yt[1][2] .= ["0", "2.5Γ—10^{βˆ’6}", "5.0Γ—10^{βˆ’6}", "7.5Γ—10^{βˆ’6}", "1.0Γ—10^{βˆ’5}"]

plot!(p, yticks=yt[1], tickfontsize=6)

With a bit more work below.

CODE: to programmatically edit scientific plot ticks
using Format, Plots

function sci_ticks(yt; precision=1)
    # "Γ—" can be typed by \times<tab>
    vs = [String.(split(y,'Γ—')) for y in yt[1][2]]
    ix = findall(x->length(x)==1, vs)
    for i in eachindex(vs)
        i ∈ ix ? (vs[i] = [vs[i][1], ""]) : (vs[i][2] = "Γ—" * vs[i][2])
    end
    ystr = format.(parse.(Float64, first.(vs)), precision=precision)
    yt[1][2] .= ystr .* last.(vs)
    return yt[1]
end

x = 0:1:10
p = plot(x, x*1e-6, yformatter=:scientific)
plot!(p, yticks=sci_ticks(yticks(p); precision=1), tickfontsize=6)
1 Like

Actually, there is a simple way to handle your example:

plot(x, x*1e-6, yformatter=x->round(x,sigdigits=1))
2 Likes

First, thank you very much for all your answers.
It is not clear to me if yformatter does format only the yticks or the values themselves.
Anyhow, with your new solution, I cannot for example have the value with no digits
(like 2x10^-6 instead of 2.0x10^-6).
(I tried that : )
plot(x, x*1e-6, yformatter=x->round(x,sigdigits=0))

Indeed, this simple approach doesn’t seem to work when asking for zero digits for numbers < 1.

Another alternative using Printf.jl:

using Printf
plot(x, x*1e-6, yformatter=x->join(split(@sprintf("%.0e", x), 'e'), "Γ—10^{") * "}")