Improve data preprocessing for bar and histogram plots
Fixes broken bar-plots with non-numeric a-axes
This commit is contained in:
parent
a523903c15
commit
67b4157e25
@ -323,7 +323,7 @@ end
|
|||||||
|
|
||||||
# create a bar plot as a filled step function
|
# create a bar plot as a filled step function
|
||||||
@recipe function f(::Type{Val{:bar}}, x, y, z)
|
@recipe function f(::Type{Val{:bar}}, x, y, z)
|
||||||
procx, procy, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
procx, procy, xscale, yscale, baseline, wautolims = _preprocess_barlike(d, x, y)
|
||||||
nx, ny = length(procx), length(procy)
|
nx, ny = length(procx), length(procy)
|
||||||
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
|
axis = d[:subplot][isvertical(d) ? :xaxis : :yaxis]
|
||||||
cv = [discrete_value!(axis, xi)[1] for xi=procx]
|
cv = [discrete_value!(axis, xi)[1] for xi=procx]
|
||||||
@ -380,6 +380,7 @@ end
|
|||||||
x := xseg.pts
|
x := xseg.pts
|
||||||
y := yseg.pts
|
y := yseg.pts
|
||||||
seriestype := :shape
|
seriestype := :shape
|
||||||
|
ylims --> wautolims
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
@deps bar shape
|
@deps bar shape
|
||||||
@ -402,39 +403,64 @@ function _scale_adjusted_values{T<:AbstractFloat}(::Type{T}, V::AbstractVector,
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _hist_ylim_lo{T<:Real}(ymin::T, yscale::Symbol)
|
|
||||||
if (yscale in _logScales)
|
function _binbarlike_baseline{T<:Real}(min_value::T, scale::Symbol)
|
||||||
ymin / T(_logScaleBases[yscale]^log10(2))
|
if (scale in _logScales)
|
||||||
|
!isnan(min_value) ? min_value / T(_logScaleBases[scale]^log10(2)) : T(1E-3)
|
||||||
else
|
else
|
||||||
zero(T)
|
zero(T)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function _hist_ylim_hi{T<:Real}(ymax::T, yscale::Symbol)
|
function _binbarlike_autolims{T<:Real}(min_value::T, max_value::T, scale::Symbol)
|
||||||
if (yscale in _logScales)
|
lo = if (scale in _logScales)
|
||||||
ymax * T(_logScaleBases[yscale]^log10(2))
|
_binbarlike_baseline(min_value, scale)
|
||||||
else
|
else
|
||||||
ymax * T(1.1)
|
min(min_value * T(1.1), zero(T))
|
||||||
end
|
end::T
|
||||||
|
|
||||||
|
hi = if !isnan(max_value)
|
||||||
|
if (scale in _logScales)
|
||||||
|
max_value * T(_logScaleBases[scale]^log10(2))
|
||||||
|
else
|
||||||
|
max(max_value * T(1.1), zero(T))
|
||||||
|
end
|
||||||
|
else
|
||||||
|
one(T)
|
||||||
|
end::T
|
||||||
|
|
||||||
|
(lo, hi)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function _preprocess_binbarlike_weights{T<:AbstractFloat}(::Type{T}, w, wscale::Symbol)
|
||||||
|
w_adj = _scale_adjusted_values(T, w, wscale)
|
||||||
|
w_min = minimum(w_adj)
|
||||||
|
w_max = maximum(w_adj)
|
||||||
|
baseline = _binbarlike_baseline(w_min, wscale)
|
||||||
|
autolims = _binbarlike_autolims(w_min, w_max,wscale)
|
||||||
|
w_adj, baseline, autolims
|
||||||
|
end
|
||||||
|
|
||||||
|
function _preprocess_barlike(d, x, y)
|
||||||
|
xscale = get(d, :xscale, :identity)
|
||||||
|
yscale = get(d, :yscale, :identity)
|
||||||
|
weights, baseline, wautolims = _preprocess_binbarlike_weights(float(eltype(y)), y, yscale)
|
||||||
|
x, weights, xscale, yscale, baseline, wautolims
|
||||||
|
end
|
||||||
|
|
||||||
function _preprocess_binlike(d, x, y)
|
function _preprocess_binlike(d, x, y)
|
||||||
xscale = get(d, :xscale, :identity)
|
xscale = get(d, :xscale, :identity)
|
||||||
yscale = get(d, :yscale, :identity)
|
yscale = get(d, :yscale, :identity)
|
||||||
|
|
||||||
T = float(promote_type(eltype(x), eltype(y)))
|
T = float(promote_type(eltype(x), eltype(y)))
|
||||||
edge = map(T, x)
|
edge = T.(x)
|
||||||
weights = _scale_adjusted_values(T, y, yscale)
|
weights, baseline, wautolims = _preprocess_binbarlike_weights(T, y, yscale)
|
||||||
w_min = minimum(weights)
|
edge, weights, xscale, yscale, baseline, wautolims
|
||||||
baseline = _hist_ylim_lo(isnan(w_min) ? one(T) : w_min, yscale)
|
|
||||||
edge, weights, xscale, yscale, baseline
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@recipe function f(::Type{Val{:barbins}}, x, y, z)
|
@recipe function f(::Type{Val{:barbins}}, x, y, z)
|
||||||
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||||
if (d[:bar_width] == nothing)
|
if (d[:bar_width] == nothing)
|
||||||
bar_width := diff(edge)
|
bar_width := diff(edge)
|
||||||
end
|
end
|
||||||
@ -447,7 +473,7 @@ end
|
|||||||
|
|
||||||
|
|
||||||
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
@recipe function f(::Type{Val{:scatterbins}}, x, y, z)
|
||||||
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||||
xerror := diff(edge)/2
|
xerror := diff(edge)/2
|
||||||
x := _bin_centers(edge)
|
x := _bin_centers(edge)
|
||||||
y := weights
|
y := weights
|
||||||
@ -512,7 +538,7 @@ end
|
|||||||
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
|
@recipe function f(::Type{Val{:stepbins}}, x, y, z)
|
||||||
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
|
axis = d[:subplot][Plots.isvertical(d) ? :xaxis : :yaxis]
|
||||||
|
|
||||||
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, x, y)
|
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, x, y)
|
||||||
|
|
||||||
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
|
xpts, ypts = _stepbins_path(edge, weights, baseline, xscale, yscale)
|
||||||
if !isvertical(d)
|
if !isvertical(d)
|
||||||
@ -539,7 +565,7 @@ end
|
|||||||
y := ypts
|
y := ypts
|
||||||
seriestype := :path
|
seriestype := :path
|
||||||
|
|
||||||
ylims --> [baseline, _hist_ylim_hi(maximum(weights), yscale)]
|
ylims --> wautolims
|
||||||
()
|
()
|
||||||
end
|
end
|
||||||
Plots.@deps stepbins path
|
Plots.@deps stepbins path
|
||||||
@ -639,7 +665,7 @@ end
|
|||||||
|
|
||||||
if d[:seriestype] == :scatterbins
|
if d[:seriestype] == :scatterbins
|
||||||
# Workaround, error bars currently not set correctly by scatterbins
|
# Workaround, error bars currently not set correctly by scatterbins
|
||||||
edge, weights, xscale, yscale, baseline = _preprocess_binlike(d, h.edges[1], h.weights)
|
edge, weights, xscale, yscale, baseline, wautolims = _preprocess_binlike(d, h.edges[1], h.weights)
|
||||||
xerror --> diff(h.edges[1])/2
|
xerror --> diff(h.edges[1])/2
|
||||||
seriestype := :scatter
|
seriestype := :scatter
|
||||||
(Plots._bin_centers(edge), weights)
|
(Plots._bin_centers(edge), weights)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user