# Log scale in histogram

I don’t mind specifying my histogram bins manually in order to get a log scale, but it appears to break the viewport in Plots.jl:

``````using Plots
x = rand(1000)
b = 10.0 .^ (-5:0)
histogram(x, bins=b)
``````

And setting the x-axis to a log scale is even worse:

``````histogram(x, bins=b, xscale=:log10, yscale=:identity)
``````

First solution: Use `norm = true` (pdf-like histogram)

``````using Plots
x = rand(10^6)
b = 10.0 .^ (-5:0)
histogram(x; alpha=0.3, label="", bin=b, norm=true)
``````

Second solution: Manually use `StatsBase.fit(Histogram{Float64}, x, b)`.

``````using Plots, StatsBase
x = rand(10^6)
b = 10.0 .^ (-5:0)
h = fit(Histogram{Float64}, x, b)
h.weights ./= diff(h.edges[1])
plot(h; alpha=0.3, label="")
``````

Another example:

``````using Plots, StatsBase, Random
X = 3randexp(10^6)
bin = [0; [2^(k/2) - 2^(-1/2) for k in 0:8]]
@show round.(bin; digits=2)
h = fit(Histogram{Float64}, X, bin)
h.weights ./= diff(h.edges[1])
plot(h; alpha=0.3, label="")
``````
``````round.(bin; digits = 2) = [0.0, 0.29, 0.71, 1.29, 2.12, 3.29, 4.95, 7.29, 10.61, 15.29]
``````

2 Likes

Thank you for these suggestions. What about getting a log scale on the x axis?

It seems to work using Plots.jl pyplot() backend and the `xaxis` keyword:

``````using Plots; pyplot()
x = rand(1000)
b = 10.0 .^ (-5:0)
# histogram(x, bins=b)  # works OK
histogram(x, bins=b, xaxis=(:log10, (0.001, 10)), yscale=:identity)
``````

1 Like

It seems to work well if you set `xlim=extrema(b)` as well as `xscale=:log10`.

``````using Plots
n = 10^6
f(x) = n * x * log(10)
x = rand(n)
b = 10.0 .^ (-5:0)
histogram(x; alpha=0.3, label="", bin=b, xscale=:log10, xlim=extrema(b))
x = 10.0 .^ (-5:0.01:0)
plot!(x, f; label="n × pdf on log-scaled xaxis", legend=:topleft)
``````

``````using Plots
n = 10^6
f(x) = n * x * log(10)
x = rand(n)
b = 10.0 .^ (-5:0.2:0)
histogram(x; alpha=0.3, label="", bin=b, xscale=:log10, xlim=extrema(b))
x = 10.0 .^ (-5:0.01:0)
plot!(x, f; label="n × pdf on log-scaled xaxis", legend=:topleft)
``````

``````using Plots, StatsBase
n = 10^6
f(x) = n * x * log(10)
x = rand(n)
b = 10.0 .^ (-5:0.2:0)
h = fit(Histogram{Float64}, x, b)
h.weights ./= diff(log10.(h.edges[1]))
plot(h; alpha=0.3, label="", xscale=:log10, xlim=extrema(b))
x = 10.0 .^ (-5:0.01:0)
plot!(x, f; label="n × pdf on log-scaled xaxis", legend=:topleft)
``````

Another example

``````using Plots, StatsBase, Random
n = 10^6
f(x) = n * exp(-x/3)/3 * x * log(10)
X = 3randexp(10^6)
bin = [1e-3; [2^(k/2) - 2^(-1/2) for k in 0:8]]
@show round.(bin; digits=2)
h = fit(Histogram{Float64}, X, bin)
h.weights ./= diff(log10.(h.edges[1]))
plot(h; alpha=0.3, label="", xscale=:log10, xlim=extrema(bin))
x = exp.(range(log.(extrema(bin))...; length=500))
plot!(x, f; label="n × pdf on log-scaled xaxis", legend=:topleft)
``````
``````round.(bin; digits = 2) = [0.0, 0.29, 0.71, 1.29, 2.12, 3.29, 4.95, 7.29, 10.61, 15.29]
``````

Edit: Update examples.

1 Like

There’s an extrema function? God, if I owed you a nickle for every time I have typed `xlim=(min(x), max(x))`

Thank you for the tip.

1 Like