Skip to content

Commit

Permalink
BandGeometry
Browse files Browse the repository at this point in the history
  • Loading branch information
CiaranOMara committed Nov 24, 2019
1 parent 78e4c9a commit cb916d1
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 23 deletions.
10 changes: 5 additions & 5 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@ Each release typically has a number of minor bug fixes beyond what is listed her
# Version 1.x
* Add `Geom.blank` (#1345)
* Support DataFrames.jl 0.19 changes in indexing (#1318)
* Add `Geom.hband` and `Geom.vband` geometries (#1264)
* Allow elements of type `Measure` to pass through `coord.jl` and `statistics.jl` (#1264)



# Version 1.1.0
* Add `alpha` aesthetic, `Scale.alpha_continuous` and `Scale.alpha_discrete` (#1252)
* Add `limits=(min= , max= )` to `Stat.histogram` (#1249)
* Add dodged boxplots (#1246)
* Add `Stat.dodge` (#1240)
* Add `Stat.dodge` (#1240)
* `Stat.smooth(method=:lm)` confidence bands (#1231)
* Support AbstractVectors everywhere (e.g. `Guide.xticks(ticks=1:10)`) (#1293)

Expand All @@ -24,7 +26,7 @@ Each release typically has a number of minor bug fixes beyond what is listed her
# Version 0.8.0
* Add `linestyle` aesthetic (#1181)
* Add `Guide.shapekey` (#1156)
* `Geom.contour`: add support for `DataFrame` (#1150)
* `Geom.contour`: add support for `DataFrame` (#1150)

# Version 0.7.0

Expand All @@ -43,7 +45,7 @@ Each release typically has a number of minor bug fixes beyond what is listed her
# Version 0.6.4

* Regression testing tools (#1020)

# Version 0.6.3

* Wide format data (#1013)
Expand Down Expand Up @@ -234,5 +236,3 @@ Each release typically has a number of minor bug fixes beyond what is listed her
keys are wrapped automatically.

* Default Theme changes.


43 changes: 30 additions & 13 deletions docs/src/gallery/geometries.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,30 @@ p1 = plot(dataset("ggplot2", "mpg"),
Guide.annotation(compose(context(), text(6,4, "y=x", hleft, vtop), fill("red"))))
x = [20*rand(20); exp(-3)]
D = DataFrame(x=x, y= exp.(-0.5*asinh.(x).+5) .+ 2*randn(length(x)))
D = DataFrame(x=x, y= exp.(-0.5*asinh.(x).+5) .+ 2*randn(length(x)))
abline = Geom.abline(color="red", style=:dash)
p2 = plot(D, x=:x, y=:y, Geom.point, Scale.x_asinh, Scale.y_log,
intercept=[148], slope=[-0.5], abline)
hstack(p1, p2)
```

## [`Geom.band`](@ref), [`Geom.hband`](@ref), [`Geom.vband`](@ref)


```@example
using Colors, Dates, Gadfly, RDatasets
Dp = dataset("ggplot2","presidential")[3:end,:]
De = dataset("ggplot2","economics")
De.Unemploy /= 10^3
plot(De, x=:Date, y=:Unemploy, Geom.line,
layer(Dp, xmin=:Start, xmax=:End, Geom.vband, color=:Party),
Scale.color_discrete_manual("deepskyblue", "lightcoral"),
Coord.cartesian(xmin=Date("1965-01-01"), ymax=12),
Guide.xlabel("Time"), Guide.ylabel("Unemployment (x10³)"), Guide.colorkey(title=""),
Theme(default_color="black", key_position=:top))
```

## [`Geom.bar`](@ref)

Expand Down Expand Up @@ -75,7 +92,7 @@ set_default_plot_size(21cm, 8cm)
singers, salaries = dataset("lattice", "singer"), dataset("car","Salaries")
salaries.Salary /= 1000.0
salaries.Discipline = ["Discipline $(x)" for x in salaries.Discipline]
p1 = plot(singers, x=:VoicePart, y=:Height, Geom.boxplot,
p1 = plot(singers, x=:VoicePart, y=:Height, Geom.boxplot,
Theme(default_color="MidnightBlue"))
p2 = plot(salaries, x=:Discipline, y=:Salary, color=:Rank,
Scale.x_discrete(levels=["Discipline A", "Discipline B"]),
Expand Down Expand Up @@ -128,7 +145,7 @@ using Gadfly, RDatasets, Distributions
set_default_plot_size(14cm, 8cm)
dist = MixtureModel(Normal, [(0.5, 0.2), (1, 0.1)])
xs = rand(dist, 10^5)
plot(layer(x=xs, Geom.density, Theme(default_color="orange")),
plot(layer(x=xs, Geom.density, Theme(default_color="orange")),
layer(x=xs, Geom.density(bandwidth=0.0003), Theme(default_color="green")),
layer(x=xs, Geom.density(bandwidth=0.25), Theme(default_color="purple")),
Guide.manual_color_key("bandwidth", ["auto", "bw=0.0003", "bw=0.25"],
Expand Down Expand Up @@ -185,9 +202,9 @@ ys = mean.(rand.(Normal.(0, sds), n))
df = DataFrame(x=1:length(sds), y=ys,
mins=ys.-(1.96*sds/sqrt(n)), maxs=ys.+(1.96*sds/sqrt(n)),
g=repeat(["a","b"], inner=3))
p1 = plot(df, x=1:length(sds), y=:y, ymin=:mins, ymax=:maxs, color=:g,
p1 = plot(df, x=1:length(sds), y=:y, ymin=:mins, ymax=:maxs, color=:g,
Geom.point, Geom.errorbar)
p2 = plot(df, y=1:length(sds), x=:y, xmin=:mins, xmax=:maxs, color=:g,
p2 = plot(df, y=1:length(sds), x=:y, xmin=:mins, xmax=:maxs, color=:g,
Geom.point, Geom.errorbar)
hstack(p1, p2)
```
Expand All @@ -202,18 +219,18 @@ df = by(salaries, [:Rank,:Discipline], :Salary=>mean, :Salary=>std)
df.ymin, df.ymax = df.Salary_mean.-df.Salary_std, df.Salary_mean.+df.Salary_std
df.label = string.(round.(Int, df.Salary_mean))
p1 = plot(df, x=:Discipline, y=:Salary_mean, color=:Rank,
p1 = plot(df, x=:Discipline, y=:Salary_mean, color=:Rank,
Scale.x_discrete(levels=["Discipline A", "Discipline B"]),
ymin=:ymin, ymax=:ymax, Geom.errorbar, Stat.dodge,
Geom.bar(position=:dodge),
Geom.bar(position=:dodge),
Scale.color_discrete(levels=["Prof", "AssocProf", "AsstProf"]),
Guide.colorkey(title="", pos=[0.76w, -0.38h]),
Theme(bar_spacing=0mm, stroke_color=c->"black")
)
p2 = plot(df, y=:Discipline, x=:Salary_mean, color=:Rank,
p2 = plot(df, y=:Discipline, x=:Salary_mean, color=:Rank,
Coord.cartesian(yflip=true), Scale.y_discrete,
xmin=:ymin, xmax=:ymax, Geom.errorbar, Stat.dodge(axis=:y),
Geom.bar(position=:dodge, orientation=:horizontal),
Geom.bar(position=:dodge, orientation=:horizontal),
Scale.color_discrete(levels=["Prof", "AssocProf", "AsstProf"]),
Guide.yticks(orientation=:vertical), Guide.ylabel(nothing),
Theme(bar_spacing=0mm, stroke_color=c->"gray")
Expand Down Expand Up @@ -440,7 +457,7 @@ x, y = cumsum(randn(n)), cumsum(randn(n))
D = DataFrame(x1=x[1:end-1], y1=y[1:end-1], x2=x[2:end], y2=y[2:end], colv=1:n-1)
palettef(c::Float64) = get(ColorSchemes.viridis, c)
plot(D, x=:x1, y=:y1, xend=:x2, yend=:y2,
plot(D, x=:x1, y=:y1, xend=:x2, yend=:y2,
color = :colv, Geom.segment, Coord.cartesian(aspect_ratio=1.0),
Scale.color_continuous(colormap=palettef, minvalue=0, maxvalue=1000)
)
Expand Down Expand Up @@ -557,16 +574,16 @@ using Gadfly, RDatasets
set_default_plot_size(21cm, 8cm)
coord = Coord.cartesian(xmin=-2, xmax=2, ymin=-2, ymax=2)
p1 = plot(coord, z=(x,y)->x*exp(-(x^2+y^2)),
xmin=[-2], xmax=[2], ymin=[-2], ymax=[2],
p1 = plot(coord, z=(x,y)->x*exp(-(x^2+y^2)),
xmin=[-2], xmax=[2], ymin=[-2], ymax=[2],
# or: x=-2:0.25:2.0, y=-2:0.25:2.0,
Geom.vectorfield(scale=0.4, samples=17), Geom.contour(levels=6),
Scale.x_continuous(minvalue=-2.0, maxvalue=2.0),
Scale.y_continuous(minvalue=-2.0, maxvalue=2.0),
Guide.xlabel("x"), Guide.ylabel("y"), Guide.colorkey(title="z"))
volcano = Matrix{Float64}(dataset("datasets", "volcano"))
volc = volcano[1:4:end, 1:4:end]
volc = volcano[1:4:end, 1:4:end]
coord = Coord.cartesian(xmin=1, xmax=22, ymin=1, ymax=16)
p2 = plot(coord, z=volc, x=1.0:22, y=1.0:16,
Geom.vectorfield(scale=0.05), Geom.contour(levels=7),
Expand Down
8 changes: 4 additions & 4 deletions src/coord.jl
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function apply_coordinate(coord::Cartesian, aess::Vector{Gadfly.Aesthetics},
for var in coord.xvars
for aes in aess
vals = getfield(aes, var)
vals === nothing && continue
(vals === nothing || eltype(vals) <: Measure) && continue

if !isa(vals, AbstractArray)
vals = [vals]
Expand All @@ -172,7 +172,7 @@ function apply_coordinate(coord::Cartesian, aess::Vector{Gadfly.Aesthetics},
for var in coord.yvars
for aes in aess
vals = getfield(aes, var)
vals === nothing && continue
(vals === nothing || eltype(vals) <: Measure) && continue

# Outliers is an odd aesthetic that needs special treatment.
if var == :outliers
Expand Down Expand Up @@ -223,12 +223,12 @@ function apply_coordinate(coord::Cartesian, aess::Vector{Gadfly.Aesthetics},
ymin = coord.ymin === nothing ? ymin : coord.ymin
ymax = coord.ymax === nothing ? ymax : coord.ymax

if xmin === nothing || !isfinite(xmin)
if xmin === nothing || isa(xmin, Measure) || !isfinite(xmin)
xmin = 0.0
xmax = 1.0
end

if ymin === nothing || !isfinite(ymin)
if ymin === nothing || isa(ymin, Measure) || !isfinite(ymin)
ymin = 0.0
ymax = 1.0
end
Expand Down
28 changes: 28 additions & 0 deletions src/geom/hvband.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Geom.band[(; orientation=:vertical)]
Draw bands across the plot canvas with a horizontal span specifed by `xmin` and `xmax` if `orientation` is `:vertical`, or a vertical span specified by `ymin` and `ymax` if the `orientation` is `:horizontal`.
This geometry is equivalent to [`Geom.rect`](@ref) with [`Stat.band`](@ref).
"""
band(; orientation=:vertical) = RectangularBinGeometry(Stat.band(orientation)) #TODO: use RectangularGeometry when it becomes available.


"""
Geom.hband[()]
Draw horizontal bands across the plot canvas with a vertical span specified by `ymin` and `ymax` aesthetics.
This geometry is equivalent to [`Geom.band`](@ref) with `orientation` set to `:vertical`.
"""
hband() = band(orientation = :horizontal)


"""
Geom.vband[()]
Draw vertical bands across the plot canvas with a horizontal span specified by `xmin` and `xmax` aesthetics.
This geometry is equivalent to [`Geom.band`](@ref).
"""
const vband = band
1 change: 1 addition & 0 deletions src/geometry.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ include("geom/boxplot.jl")
include("geom/errorbar.jl")
include("geom/hexbin.jl")
include("geom/hvabline.jl")
include("geom/hvband.jl")
include("geom/label.jl")
include("geom/line.jl")
include("geom/point.jl")
Expand Down
45 changes: 44 additions & 1 deletion src/statistics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,49 @@ apply_statistic(stat::Identity,
"""
const identity = Identity

struct BandStatistic <: Gadfly.StatisticElement
orientation::Symbol # :horizontal or :vertical
end

function BandStatistic(; orientation=:vertical)
return BandStatistic(orientation)
end

input_aesthetics(stat::BandStatistic) = [:xmin, :xmax, :ymin, :ymax]
output_aesthetics(stat::BandStatistic) = [:xmin, :xmax, :ymin, :ymax]
default_scales(stat::BandStatistic) = [Scale.x_continuous(), Scale.y_continuous()]

"""
Stat.band[(; orientation=:vertical)]
Transform points in $(aes2str(input_aesthetics(band()))) into rectangles in
$(aes2str(output_aesthetics(band()))). Used by [`Geom.band`](@ref Gadfly.Geom.band).
"""
const band = BandStatistic

function apply_statistic(stat::BandStatistic,
scales::Dict{Symbol, Gadfly.ScaleElement},
coord::Gadfly.CoordinateElement,
aes::Gadfly.Aesthetics)

if stat.orientation == :horizontal

n = max(length(aes.ymin)) #Note: already passed check for equal lengths.

aes.xmin = fill(0w, n)
aes.xmax = fill(1w, n)

elseif stat.orientation == :vertical

n = max(length(aes.xmin)) #Note: already passed check for equal lengths.

aes.ymin = fill(0h, n)
aes.ymax = fill(1h, n)

else
error("Orientation must be :horizontal or :vertical")
end
end

# Determine bounds of bars positioned at the given values.
function barminmax(vals, iscontinuous::Bool)
Expand Down Expand Up @@ -779,7 +822,7 @@ function apply_statistic(stat::TickStatistic,
for var in in_vars
categorical && !in(var,[:x,:y]) && continue
vals = getfield(aes, var)
if vals != nothing && eltype(vals) != Function
if vals != nothing && eltype(vals) != Function && !(eltype(vals) <: Measure)
if minval == nothing
minval = first(vals)
end
Expand Down
8 changes: 8 additions & 0 deletions test/testscripts/hvband.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using Gadfly
set_default_plot_size(21cm, 8cm)

p1 = plot(xmin=[1.0, 5.0, 7.0], xmax=[2.0, 6.5, 8.0] , Geom.vband, Theme(default_color="green"));

p2 = plot(ymin=[2.5], ymax=[7.5], Geom.hband, Theme(default_color="red"));

hstack(p1, p2)

0 comments on commit cb916d1

Please sign in to comment.