added violin plot
This commit is contained in:
parent
f3f29fb54f
commit
fdf3b3f581
@ -68,6 +68,8 @@ export
|
||||
abline!,
|
||||
boxplot,
|
||||
boxplot!,
|
||||
violin,
|
||||
violin!,
|
||||
|
||||
title!,
|
||||
xlabel!,
|
||||
@ -192,6 +194,8 @@ scatter3d(args...; kw...) = plot(args...; kw..., linetype = :scatter3d)
|
||||
scatter3d!(args...; kw...) = plot!(args...; kw..., linetype = :scatter3d)
|
||||
boxplot(args...; kw...) = plot(args...; kw..., linetype = :box)
|
||||
boxplot!(args...; kw...) = plot!(args...; kw..., linetype = :box)
|
||||
violin(args...; kw...) = plot(args...; kw..., linetype = :violin)
|
||||
violin!(args...; kw...) = plot!(args...; kw..., linetype = :violin)
|
||||
|
||||
|
||||
title!(s::AbstractString; kw...) = plot!(; title = s, kw...)
|
||||
|
||||
@ -11,7 +11,7 @@ const _3dTypes = [:path3d, :scatter3d, :surface, :wireframe]
|
||||
const _allTypes = vcat([
|
||||
:none, :line, :path, :steppre, :steppost, :sticks, :scatter,
|
||||
:heatmap, :hexbin, :hist, :hist2d, :hist3d, :density, :bar, :hline, :vline, :ohlc,
|
||||
:contour, :pie, :shape, :box
|
||||
:contour, :pie, :shape, :box, :violin
|
||||
], _3dTypes)
|
||||
@compat const _typeAliases = KW(
|
||||
:n => :none,
|
||||
|
||||
@ -80,7 +80,7 @@ supportedArgs(::GadflyBackend) = [
|
||||
]
|
||||
supportedAxes(::GadflyBackend) = [:auto, :left]
|
||||
supportedTypes(::GadflyBackend) = [:none, :line, :path, :steppre, :steppost, :sticks,
|
||||
:scatter, :hist2d, :hexbin, :hist, :bar, :box,
|
||||
:scatter, :hist2d, :hexbin, :hist, :bar, :box, :violin,
|
||||
:hline, :vline, :contour, :shape]
|
||||
supportedStyles(::GadflyBackend) = [:auto, :solid, :dash, :dot, :dashdot, :dashdotdot]
|
||||
supportedMarkers(::GadflyBackend) = vcat(_allMarkers, Shape)
|
||||
@ -167,7 +167,7 @@ supportedArgs(::PyPlotBackend) = [
|
||||
]
|
||||
supportedAxes(::PyPlotBackend) = _allAxes
|
||||
supportedTypes(::PyPlotBackend) = [:none, :line, :path, :steppre, :steppost, #:sticks,
|
||||
:scatter, :hist2d, :hexbin, :hist, :density, :bar, :box,
|
||||
:scatter, :hist2d, :hexbin, :hist, :density, :bar, :box, :violin,
|
||||
:hline, :vline, :contour, :path3d, :scatter3d, :surface, :wireframe, :heatmap]
|
||||
supportedStyles(::PyPlotBackend) = [:auto, :solid, :dash, :dot, :dashdot]
|
||||
# supportedMarkers(::PyPlotBackend) = [:none, :auto, :rect, :ellipse, :diamond, :utriangle, :dtriangle, :cross, :xcross, :star5, :hexagon]
|
||||
|
||||
@ -43,6 +43,8 @@ apply_series_recipe(d::KW, lt) = KW[d]
|
||||
# -------------------------------------------------
|
||||
# Box Plot
|
||||
|
||||
const _box_halfwidth = 0.4
|
||||
|
||||
function apply_series_recipe(d::KW, ::Type{Val{:box}})
|
||||
# dumpdict(d, "box before", true)
|
||||
# TODO: add scatter series with outliers
|
||||
@ -58,7 +60,7 @@ function apply_series_recipe(d::KW, ::Type{Val{:box}})
|
||||
q1,q2,q3,q4,q5 = quantile(d[:y][groupby.groupIds[i]], linspace(0,1,5))
|
||||
|
||||
# make the shape
|
||||
l, m, r = i - 0.3, i, i + 0.3
|
||||
l, m, r = i - _box_halfwidth, i, i + _box_halfwidth
|
||||
xcoords = [
|
||||
m, l, r, m, m, NaN, # lower T
|
||||
l, l, r, r, l, NaN, # lower box
|
||||
@ -80,6 +82,58 @@ function apply_series_recipe(d::KW, ::Type{Val{:box}})
|
||||
KW[d]
|
||||
end
|
||||
|
||||
# -------------------------------------------------
|
||||
# Violin Plot
|
||||
|
||||
try
|
||||
Pkg.installed("KernelDensity")
|
||||
import KernelDensity
|
||||
|
||||
warn("using KD for violin")
|
||||
function violin_coords(y)
|
||||
kd = KernelDensity.kde(y, npoints = 30)
|
||||
kd.density, kd.x
|
||||
end
|
||||
catch
|
||||
warn("using hist for violin")
|
||||
function violin_coords(y)
|
||||
edges, widths = hist(y, 20)
|
||||
centers = 0.5 * (edges[1:end-1] + edges[2:end])
|
||||
ymin, ymax = extrema(y)
|
||||
vcat(0.0, widths, 0.0), vcat(ymin, centers, ymax)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function apply_series_recipe(d::KW, ::Type{Val{:violin}})
|
||||
# dumpdict(d, "box before", true)
|
||||
# TODO: add scatter series with outliers
|
||||
|
||||
# create a list of shapes, where each shape is a single boxplot
|
||||
shapes = Shape[]
|
||||
d[:linetype] = :shape
|
||||
groupby = extractGroupArgs(d[:x])
|
||||
|
||||
for (i, glabel) in enumerate(groupby.groupLabels)
|
||||
|
||||
# get the edges and widths
|
||||
y = d[:y][groupby.groupIds[i]]
|
||||
widths, centers = violin_coords(y)
|
||||
|
||||
# normalize
|
||||
widths = _box_halfwidth * widths / maximum(widths)
|
||||
|
||||
# make the violin
|
||||
xcoords = vcat(widths, -reverse(widths)) + i
|
||||
ycoords = vcat(centers, reverse(centers))
|
||||
push!(shapes, Shape(xcoords, ycoords))
|
||||
end
|
||||
|
||||
d[:x], d[:y] = shape_coords(shapes)
|
||||
d[:plotarg_overrides] = KW(:xticks => (1:length(shapes), groupby.groupLabels))
|
||||
|
||||
KW[d]
|
||||
end
|
||||
|
||||
# -------------------------------------------------
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user