275 lines
12 KiB
Markdown
275 lines
12 KiB
Markdown
# Plots
|
|
|
|
[](https://travis-ci.org/tbreloff/Plots.jl)
|
|
|
|
#### Author: Thomas Breloff (@tbreloff)
|
|
|
|
Plots is a plotting interface and wrapper for several plotting packages. My goals with the package are:
|
|
|
|
- Simple. The interface should be intuitive enough that someone coming from Matlab, Python, etc can immediately start generating complex plots without reading volumes of documentation.
|
|
- Automatic (if you want). There should be smart defaults for the most common functionality, and simple, high-level ways to override complex functionality.
|
|
- Flexible. You should be able to produce your favorite plot in your favorite package, but quicker and simpler.
|
|
- Consistent. Don't commit to one graphics package. One command will switch your backend, and the exact same plotting commands will work with a very different underlying backend.
|
|
|
|
Please add wishlist items, bugs, or any other comments/questions to the issues list.
|
|
|
|
Check out the [summary graphs](img/supported/supported.md) for the features that each backend supports.
|
|
|
|
## Examples for each implemented backend:
|
|
|
|
- [Qwt.jl](docs/qwt_examples.md)
|
|
- [Gadfly.jl](docs/gadfly_examples.md)
|
|
- [UnicodePlots.jl](docs/unicodeplots_examples.md)
|
|
- [PyPlot.jl](docs/pyplot_examples.md)
|
|
- [Immerse.jl](docs/immerse_examples.md)
|
|
- [Winston.jl](docs/winston_examples.md)
|
|
|
|
## Installation
|
|
|
|
First, add the package
|
|
|
|
```julia
|
|
Pkg.add("Plots")
|
|
```
|
|
|
|
then get any plotting packages you need (obviously, you should get at least one backend):
|
|
|
|
```julia
|
|
Pkg.add("Gadfly")
|
|
Pkg.add("Immerse")
|
|
Pkg.add("UnicodePlots")
|
|
Pkg.add("PyPlot") # requires python and matplotlib
|
|
Pkg.clone("https://github.com/tbreloff/Qwt.jl.git") # requires pyqt and pyqwt
|
|
Pkg.add("Winston")
|
|
```
|
|
|
|
## Use
|
|
|
|
Load it in. The underlying plotting backends are not imported until `backend()` is called (which happens
|
|
on your first call to `plot` or `subplot`). This means that you don't need any backends to be installed when you call `using Plots`.
|
|
Plots will try to figure out a good default backend for you automatically based on what backends are installed.
|
|
|
|
```julia
|
|
using Plots
|
|
```
|
|
|
|
Do a plot in Gadfly (inspired by [this example](http://gadflyjl.org/geom_point.html)), then save a png:
|
|
|
|
```julia
|
|
gadfly() # switch to Gadfly as a backend
|
|
dataframes() # turn on support for DataFrames inputs
|
|
|
|
# load some data
|
|
using RDatasets
|
|
iris = dataset("datasets", "iris");
|
|
|
|
# This will bring up a browser window with the plot. Add a semicolon at the end to skip display.
|
|
scatter(iris, :SepalLength, :SepalWidth, group=:Species, m=([:+ :d :s], 12))
|
|
|
|
# save a png (equivalent to png("gadfly1.png") and savefig("gadfly1.png"))
|
|
png("gadfly1")
|
|
```
|
|
|
|

|
|
|
|
See the examples pages for lots of examples of plots, and what those commands produce for each supported backend.
|
|
Also check out the [IJulia notebooks](examples) and see how it works interactively.
|
|
|
|
## API
|
|
|
|
Call `backend(backend::Symbol)` or the shorthands (`gadfly()`, `qwt()`, `unicodeplots()`, etc) to set the current plotting backend.
|
|
Subsequent commands are converted into the relevant plotting commands for that package:
|
|
|
|
```julia
|
|
gadfly()
|
|
plot(1:10) # this effectively calls `y = 1:10; Gadfly.plot(x=1:length(y), y=y)`
|
|
qwt()
|
|
plot(1:10) # this effectively calls `Qwt.plot(1:10)`
|
|
```
|
|
|
|
Use `plot` to create a new plot object, and `plot!` to add to an existing one:
|
|
|
|
```julia
|
|
plot(args...; kw...) # creates a new plot window, and sets it to be the `current`
|
|
plot!(args...; kw...) # adds to the `current`
|
|
plot!(plotobj, args...; kw...) # adds to the plot `plotobj`
|
|
```
|
|
|
|
Now that you know which plot object you're updating (new, current, or other), I'll leave it off for simplicity.
|
|
There are many ways to pass in data to the plot functions... some examples:
|
|
|
|
- Vector-like (subtypes of AbstractArray{T,1})
|
|
- Matrix-like (subtypes of AbstractArray{T,2})
|
|
- Vectors of Vectors
|
|
- Functions
|
|
- Vectors of Functions
|
|
- DataFrames with column symbols (initialize with `dataframes()`)
|
|
|
|
In general, you can pass in a `y` only, or an `x` and `y`, both of whatever type(s) you want, and Plots will slice up the data as needed.
|
|
For matrices, data is split by columns. For functions, data is mapped. For DataFrames, a Symbol/Symbols in place of x/y will map to
|
|
the relevant column(s).
|
|
|
|
Here are some example usages... remember you can always use `plot!` to update an existing plot, and that, unless specified, you will update the `current()`.
|
|
|
|
```julia
|
|
plot() # empty plot object
|
|
plot(4) # initialize with 4 empty series
|
|
plot(rand(10)) # plot 1 series... x = 1:10
|
|
plot(rand(10,5)) # plot 5 series... x = 1:10
|
|
plot(rand(10), rand(10)) # plot 1 series
|
|
plot(rand(10,5), rand(10)) # plot 5 series... y is the same for all
|
|
plot(sin, rand(10)) # y = sin(x)
|
|
plot(rand(10), sin) # same... y = sin(x)
|
|
plot([sin,cos], 0:0.1:π) # plot 2 series, sin(x) and cos(x)
|
|
plot([sin,cos], 0, π) # plot sin and cos on the range [0, π]
|
|
plot(1:10, Any[rand(10), sin]) # plot 2 series, y = rand(10) for the first, y = sin(x) for the second... x = 1:10 for both
|
|
plot(dataset("Ecdat", "Airline"), :Cost) # plot from a DataFrame (call `dataframes()` first to import DataFrames and initialize)
|
|
```
|
|
|
|
You can update certain plot settings after plot creation (not supported on all backends):
|
|
|
|
```julia
|
|
plot!(title = "New Title", xlabel = "New xlabel", ylabel = "New ylabel")
|
|
plot!(xlims = (0, 5.5), ylims = (-2.2, 6), xticks = 0:0.5:10, yticks = [0,1,5,10])
|
|
```
|
|
|
|
With `subplot`, create multiple plots at once, with flexible layout options:
|
|
|
|
```julia
|
|
y = rand(100,3)
|
|
subplot(y; n = 3) # create an automatic grid, and let it figure out the shape
|
|
subplot(y; n = 3, nr = 1) # create an automatic grid, but fix the number of rows
|
|
subplot(y; n = 3, nc = 1) # create an automatic grid, but fix the number of columns
|
|
subplot(y; layout = [1, 2]) # explicit layout. Lists the number of plots in each row
|
|
```
|
|
|
|
__Tip__: You can call `subplot!(args...; kw...)` to add to an existing subplot.
|
|
|
|
__Tip__: Calling `subplot!` on a `Plot` object, or `plot!` on a `Subplot` object will throw an error.
|
|
|
|
Shorthands:
|
|
|
|
```julia
|
|
scatter(args...; kw...) = plot(args...; kw..., linetype = :scatter)
|
|
scatter!(args...; kw...) = plot!(args...; kw..., linetype = :scatter)
|
|
bar(args...; kw...) = plot(args...; kw..., linetype = :bar)
|
|
bar!(args...; kw...) = plot!(args...; kw..., linetype = :bar)
|
|
histogram(args...; kw...) = plot(args...; kw..., linetype = :hist)
|
|
histogram!(args...; kw...) = plot!(args...; kw..., linetype = :hist)
|
|
heatmap(args...; kw...) = plot(args...; kw..., linetype = :heatmap)
|
|
heatmap!(args...; kw...) = plot!(args...; kw..., linetype = :heatmap)
|
|
sticks(args...; kw...) = plot(args...; kw..., linetype = :sticks, marker = :ellipse)
|
|
sticks!(args...; kw...) = plot!(args...; kw..., linetype = :sticks, marker = :ellipse)
|
|
hline(args...; kw...) = plot(args...; kw..., linetype = :hline)
|
|
hline!(args...; kw...) = plot!(args...; kw..., linetype = :hline)
|
|
vline(args...; kw...) = plot(args...; kw..., linetype = :vline)
|
|
vline!(args...; kw...) = plot!(args...; kw..., linetype = :vline)
|
|
ohlc(args...; kw...) = plot(args...; kw..., linetype = :ohlc)
|
|
ohlc!(args...; kw...) = plot!(args...; kw..., linetype = :ohlc)
|
|
|
|
title!(s::AbstractString) = plot!(title = s)
|
|
xlabel!(s::AbstractString) = plot!(xlabel = s)
|
|
ylabel!(s::AbstractString) = plot!(ylabel = s)
|
|
xlims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(xlims = lims)
|
|
ylims!{T<:Real,S<:Real}(lims::Tuple{T,S}) = plot!(ylims = lims)
|
|
xticks!{T<:Real}(v::AVec{T}) = plot!(xticks = v)
|
|
yticks!{T<:Real}(v::AVec{T}) = plot!(yticks = v)
|
|
xflip!(flip::Bool = true) = plot!(xflip = flip)
|
|
yflip!(flip::Bool = true) = plot!(yflip = flip)
|
|
xaxis!(args...) = plot!(xaxis = args)
|
|
yaxis!(args...) = plot!(yaxis = args)
|
|
annotate!(anns) = plot!(annotation = anns)
|
|
```
|
|
|
|
Some keyword arguments you can set:
|
|
|
|
[[KEYWORD_ARGS_TABLE]]
|
|
|
|
Plot types:
|
|
|
|
[[LINETYPES_TABLE]]
|
|
|
|
Line styles:
|
|
|
|
[[LINESTYLES_TABLE]]
|
|
|
|
Markers:
|
|
|
|
[[MARKERS_TABLE]]
|
|
|
|
|
|
__Tip__: You can see the default value for a given argument with `default(arg::Symbol)`, and set the default value with `default(arg::Symbol, value)` or `default(; kw...)`. For example set the default window size and whether we should show a legend with `default(size=(600,400), leg=false)`.
|
|
|
|
__Tip__: There are some helper arguments you can set: `xaxis`, `yaxis`, `line`, `marker`, `fill`. These go through special preprocessing to extract values into individual arguments. The order doesn't matter, and if you pass a single value it's equivalent to wrapping it in a Tuple. Examples:
|
|
|
|
```
|
|
plot(y, xaxis = ("mylabel", :log, :flip, (-1,1))) # this sets the `xlabel`, `xscale`, `xflip`, and `xlims` arguments automatically
|
|
plot(y, line = (:bar, :blue, :dot, 10)) # this sets the `linetype`, `color`, `linestyle`, and `linewidth` arguments automatically
|
|
plot(y, marker = (:rect, :red, 10)) # this sets the `markershape`, `markercolor`, and `markersize` arguments automatically
|
|
plot(y, fill = (:green, 10)) # this sets the `fillcolor` and `fillrange` arguments automatically
|
|
# Note: `fillrange` can be:
|
|
a number (fill to horizontal line)
|
|
a vector of numbers (different for each data point)
|
|
a tuple of vectors (fill a band)
|
|
```
|
|
|
|
__Tip__: When plotting multiple lines, you can set all series to use the same value, or pass in a matrix to cycle through values. Example:
|
|
|
|
```julia
|
|
plot(rand(100,4); color = [:red RGB(0,0,1)], # (Matrix) lines 1 and 3 are red, lines 2 and 4 are blue
|
|
axis = :auto, # lines 1 and 3 are on the left axis, lines 2 and 4 are on the right
|
|
markershape = [:rect, :star1] # (Vector) ALL lines are passed the vector [:rect, :star1]
|
|
width = 5) # all lines have a width of 5
|
|
```
|
|
|
|
__Tip__: Not all features are supported for each backend, but you can see what's supported by calling the functions: `supportedArgs()`, `supportedAxes()`, `supportedTypes()`, `supportedStyles()`, `supportedMarkers()`, `subplotSupported()`
|
|
|
|
__Tip__: Call `gui()` to display the plot in a window. Interactivity depends on backend. Plotting at the REPL (without semicolon) implicitly calls `gui()`.
|
|
|
|
## TODO features:
|
|
|
|
- [x] Plot vectors/matrices/functions
|
|
- [x] Plot DataFrames
|
|
- [x] Grouping
|
|
- [ ] Annotations
|
|
- [ ] Scales
|
|
- [ ] Categorical Inputs (strings, etc... for hist, bar? or can split one series into multiple?)
|
|
- [ ] Custom markers
|
|
- [ ] Special plots (boxplot, ohlc?)
|
|
- [x] Subplots
|
|
- [x] Histograms
|
|
- [ ] 3D plotting
|
|
- [ ] Scenes/Drawing
|
|
- [ ] Graphs
|
|
- [ ] Interactivity (GUIs)
|
|
|
|
## TODO backends:
|
|
|
|
- [x] Gadfly.jl
|
|
- [x] Immerse.jl
|
|
- [x] PyPlot.jl
|
|
- [x] UnicodePlots.jl
|
|
- [x] Qwt.jl
|
|
- [x] Winston.jl
|
|
- [ ] GLPlot.jl
|
|
- [ ] Bokeh.jl
|
|
- [ ] Vega.jl
|
|
- [ ] Gaston.jl
|
|
- [ ] Plotly.jl
|
|
- [ ] GoogleCharts.jl
|
|
- [ ] PLplot.jl
|
|
- [ ] TextPlots.jl
|
|
- [ ] ASCIIPlots.jl
|
|
- [ ] Sparklines.jl
|
|
- [ ] Hinton.jl
|
|
- [ ] ImageTerm.jl
|
|
- [ ] GraphViz.jl
|
|
- [ ] TikzGraphs.jl
|
|
- [ ] GraphLayout.jl
|
|
|
|
## More information on backends (both supported and unsupported)
|
|
|
|
See the wiki at: https://github.com/JuliaPlot/juliaplot_docs/wiki
|
|
|
|
|