Data Visualization in Julia: Unlocking Insights with Plots.jl
Data visualization is a critical tool in the data scientist‘s arsenal. It allows us to explore and understand patterns in data, communicate insights to stakeholders, and guide data-driven decision making. Visualizations help us unlock the stories hidden in the raw data.
As datasets grow in size and complexity, effective visualizations become even more crucial. A single graphic can convey insights that would be difficult to find by looking at raw numbers alone. According to a study by MIT, the human brain processes visual information 60,000 times faster than text. Well-designed data visualizations take advantage of this fact to help us quickly grasp key concepts.
However, big data also presents challenges for visualization. High-dimensional datasets with millions of records can be difficult to plot using traditional methods. Modern data visualization libraries need to handle these large datasets efficiently while still producing meaningful graphics.
Julia is a programming language rapidly gaining popularity for data science and machine learning due to its ease of use and high performance. Plots.jl is a powerful data visualization library that allows us to create a wide variety of plots with just a few lines of code.
In this post, we‘ll explore the capabilities of Plots.jl and show how it can be used to create beautiful, insightful visualizations. We‘ll cover basic plotting, customization, and advanced features like interactivity and animation. We‘ll also discuss tips for effective data visualization and common pitfalls to avoid.
Why Julia and Plots.jl?
Julia is a high-level, high-performance dynamic programming language designed for numerical and scientific computing. It has the ease of use of Python but the speed of C, thanks to its just-in-time compilation. This allows us to write intuitive, high-level code that performs well on large datasets.
Julia‘s popularity for data science and machine learning has grown quickly since its release in 2012. According to the 2022 Stack Overflow Developer Survey, Julia was the 4th most loved programming language, with 66% of developers expressing interest in continuing to develop with it.
Plots.jl is a popular data visualization library for Julia. It offers several key advantages:
- Consistent, intuitive API for all plot types
- Support for multiple plotting backends (GR, Plotly, PyPlot, etc.)
- Extensive customization options through keyword arguments
- High-performance for large datasets
- Interactivity, animations, and other advanced features
Plots.jl makes it easy to create complex visualizations with a simple API, while still allowing full control over the output.
Installation and Setup
To use Plots.jl, we first need to install the package and a backend. Open the Julia REPL and enter the package manager by pressing ]. Then run:
add Plots
This installs the core Plots.jl package. We also need to install at least one plotting backend. For example, to install the GR backend:
add GR
GR is a good default choice as it offers high performance and compatibility with most plot types. See the list of available backends for other options.
To use Plots.jl, we load it with:
using Plots
And select the backend with:
gr() # select the GR backend
Now we‘re ready to start plotting!
Basic Plotting with Plots.jl
Plots.jl offers a simple, consistent API for creating all kinds of plots. Let‘s start with a basic line plot:
x = 1:10
y = rand(10)
plot(x, y)
This creates a line plot of y vs x. We can also plot functions directly:
plot(sin, 0, 2π)
To plot multiple series, we pass vectors or matrices of data:
x = range(0, 10, length=100)
y1 = sin.(x)
y2 = cos.(x)
plot(x, [y1, y2])
Plots.jl creates a different colored line for each series by default. We can customize the plot using keyword arguments:
plot(x, [y1, y2],
title="Trigonometric Functions",
xlabel="x",
ylabel="y",
label=["sin(x)" "cos(x)"],
linewidth=2,
legend=:topleft)
This sets the plot title, axis labels, series labels, line width, and moves the legend to the top left corner. See the attributes documentation for the full list of customization options.
Scatter Plots
Scatter plots are useful for visualizing the relationship between two variables. We can create them using the scatter command:
x = rand(100)
y = rand(100)
scatter(x, y,
markersize=4,
markeralpha=0.6,
markercolor=:blue,
markerstrokestyle=:dot)
This plots 100 random (x, y) points with partially transparent blue dots.
Statistical Plots
Plots.jl offers several plot types useful for statistical analysis and visualization. These include:
- Histograms:
histogram(x) - Box plots:
boxplot(x, y) - Violin plots:
violin(x, y) - Density plots:
density(x)
For example, let‘s create side-by-side violin plots comparing the distributions of four datasets:
using Random
Random.seed!(123)
n = 500
data = [randn(n) .+ i for i in 1:4]
violin(data, leg=false, fillalpha=0.8)
This creates partially transparent violin plots for each dataset, showing the median, interquartile range, and distribution shape.
Heatmaps and Matrix Visualizations
Heatmaps are a great way to visualize 2D matrices of data. We can create them with the heatmap function:
using LinearAlgebra
x = 1:10
y = 1:10
z = x‘ * y
heatmap(z)
This computes the outer product of x and y and plots the resulting matrix as a heatmap.
We can customize the color scheme, add a color bar, and change the aspect ratio:
heatmap(z, clim=(0, 100), color=cgrad([:white, :red, :black]), colorbar_title="Value", ratio=1)
Machine Learning Visualizations
Data visualization is an indispensable tool for understanding machine learning models and algorithms. Plots.jl can help with common ML visualization tasks.
To create a confusion matrix from actual and predicted class labels:
using MLBase: ConfusionMatrix
actual = ["Dog", "Cat", "Dog", "Cat", "Dog"]
predicted = ["Dog", "Dog", "Cat", "Cat", "Cat"]
cm = ConfusionMatrix(actual, predicted)
heatmap(
cm.matrix,
title="Confusion Matrix",
xlabel="Predicted",
ylabel="Actual",
xticks=(1:2, ["Dog", "Cat"]),
yticks=(1:2, ["Dog", "Cat"]))
This computes the confusion matrix comparing the actual and predicted labels, and plots it as a heatmap with custom axis labels.
We can also visualize the decision boundaries of a trained classifier:
using ScikitLearn
using ScikitLearn.Datasets: make_moons
X, y = make_moons(n_samples=200, noise=0.25, random_state=1)
colors = [y == 0 ? :red : :blue for y in y]
scatter(X[:, 1], X[:, 2], color=colors, alpha=0.5, ms=5, label=false)
@sk_import svm: SVC
model = SVC(kernel="rbf", gamma=1, C=5)
fit!(model, X, y)
x1 = range(minimum(X[:,1]), maximum(X[:,1]), length=100)
x2 = range(minimum(X[:,2]), maximum(X[:,2]), length=100)
grid = [[xi, xj] for xi in x1, xj in x2]
zz = reshape(predict(model, grid), 100, 100)
contourf!(x1, x2, zz, alpha=0.4)
This loads a synthetic moon-shaped binary classification dataset, plots the datapoints colored by class, trains an SVM classifier, and plots its decision boundary. The decision boundary shows where the model predicts each class.
Interactivity and Animation
Plots.jl supports creating interactive plots that allow zooming, panning, and hover tooltips using the plotlyjs() backend. For example:
using Distributions
plotlyjs()
function interactive_histogram(dist, n)
data = rand(dist, n)
histogram(data,
nbins=30,
xlabel="Value",
ylabel="Count",
title="Interactive Histogram")
end
interactive_histogram(Normal(0, 1), 1000)
This plots an interactive histogram of 1000 samples from a normal distribution. We can zoom, pan, and see hover tooltips.
We can also create animated plots using the @animate macro:
anim = @animate for i=1:100
x = range(0, i, length=100)
y = sin.(x)
plot(x, y, legend=false)
end
gif(anim, "anim.gif", fps=20)
This generates an animation of a sine wave growing in length, and saves it to a gif.
Ecosystem and Comparisons
Plots.jl has a rich ecosystem of extension packages that provide additional functionality and plot types. Some key packages include:
- StatsPlots.jl – Statistical plotting recipes
- GraphRecipes.jl – Graph and network visualization
- AlgebraOfGraphics.jl – Grammar of graphics API
- PlotThemes.jl – Additional plot themes and color schemes
- VegaLite.jl – Grammar of interactive graphics
- Makie.jl – High-performance GPU-powered plotting
In terms of features and performance, Plots.jl compares favorably to popular plotting libraries in Python and R:
- Matplotlib (Python) – Plots.jl has similar features and customization options but a more concise syntax
- ggplot2 (R) – Plots.jl is imperative rather than declarative but offers similar statistical plotting capabilities
- Plotly (Python/R) – Plots.jl has integrated Plotly support for interactivity
Plots.jl is able to handle larger datasets than Matplotlib or ggplot2 thanks to the performance of Julia. Benchmarks show it is 5-10x faster for plotting datasets of 1 million points.
One current limitation of Plots.jl and the Julia visualization ecosystem is the lack of a mature dashboarding solution for building interactive data applications. Packages like Dash (for Plotly) and Shiny (for R) are more established. However, packages like Dash.jl and Stipple.jl are under active development to address this need.
Conclusion
Data visualization is an essential skill for data scientists and machine learning engineers. Effective visualizations allow us to explore data, build intuition, and communicate insights.
Plots.jl is a powerful and flexible tool for data visualization in Julia. It offers an intuitive API for creating all sorts of static and dynamic visualizations. Thanks to Julia‘s high performance, Plots.jl can handle larger datasets than other plotting libraries.
We‘ve only scratched the surface of what‘s possible with Plots.jl. To learn more, check out these resources:
- Plots.jl Documentation
- Julia Data Science online book
- DataCamp‘s Introduction to Julia course
Try exploring your own datasets with Plots.jl and see what insights you can uncover!