How to make this plot in Julia?

Ahh, now I got it:

using AlgebraOfGraphics, GLMakie
using Random, DataFrames
Random.seed!(123)
d = DataFrame(name = repeat(["A","B","C","D","E","F"], inner=4), 
      time=repeat([0,1,3,6], outer=6), value = rand(24));
plt = data(d)*( 
       (visual(Scatter) + visual(Lines)) * mapping(:time, :value, color = :name) + 
        visual(Makie.Text) * mapping(:time, :value, color = :name, text = :name => verbatim) 
       );
AlgebraOfGraphics.draw(plt)

Thank you for your help!

2 Likes

Here’s an example using Bokeh.jl. It’s quite long, because you need to be explicit about a lot of things, but I’ve been thinking about an AoG-style wrapper for it.

using DataFrames, Random, Bokeh
# OP's data
Random.seed!(123)
d = DataFrame(name = repeat(["A","B","C","D","E","F"], inner=4), 
      time=repeat([0,1,3,6], outer=6), value = rand(24));
# (optional) displays plots in the browser - omit if you are in a notebook
Bokeh.settings!(display=:browser)
# make the figure
fig = figure()
# set the axis labels
fig.x_axis.axis_label = "time"
fig.y_axis.axis_label = "value"
# (optional) by default the legend is placed inside the plot
plot!(fig, Legend; location="right")
# defines the mapping from names to colors
color = factor_cmap("name", "Set2_8", sort(unique(d.name)))
# defines the data source
source = ColumnDataSource(data=d)
# add scatter plot
plot!(fig, Scatter; x="time", y="value", source, color, size=10, legend_field="name")
# add text
plot!(fig, Bokeh.Text; x="time", y="value", text="name", source, color, text_baseline="middle", x_offset=10)
# add lines - note bokeh will not group lines for you, so you must
# group the data yourself and either make multiple `Line` plots or
# one `MultiLine` plot
w = combine(groupby(d, :name), d->(time=[d.time], value=[d.value]))
plot!(fig, MultiLine; xs="time", ys="value", source=w, color)
# show the result
display(fig)

Edit: here is the result.

2 Likes

Thank you @cjdoris
I’ve heard a lot of good things about Bokeh in python, but never tried it. Great that we also have it in Julia.

1 Like

I just dug out my AoG-style wrapper for Bokeh: GitHub - cjdoris/Algebrokeh.jl: Statistical plotting with Bokeh.

The gist is:

# You can't use Line glyph with color mapping, so need to explicitly
# group and use the MultiLine glyph (currently).
gd = combine(groupby(d, :name), d->(time=[d.time], value=[d.value]))
# Should look familiar to AoG users!
((data(d) * (visual(Scatter) + visual(Bokeh.Text)) + data(gd) * visual(MultiLine))
 * mapping(x="time", y="value", color="name", text="name")
) |> draw |> display

3 Likes

Did you write this 300-LOC package in less then 1h?

Lol no I wrote the code months ago and this post prompted me to put it on GitHub :slight_smile:

1 Like

AoG-style wrapper for Bokeh
Wow! This is looking great!

It would be great for this example to be in the AofG gallery.

The Makie.Text part is covered by this example: https://aog.makie.org/stable/gallery/gallery/scales/prescaled_data/#Pre-scaled-data
Not sure how typical this plot actually is. What would be a good name for it?

You can make your code a little more concise by using visual(ScatterLines). You can also use the distributive property of mappings (that’s a matter of taste, though)

	# Version 1
	plt = data(d) * 
		mapping(:time, :value, color = :name) * (
			visual(ScatterLines) + 
			visual(Makie.Text) * mapping(text = :name => verbatim)
		)

	# Version 2 (works because ScatterLines ignores unused kwarg `text`)
	plt = data(d) * 
		mapping(:time, :value, color = :name, text = :name => verbatim) *
		(visual(ScatterLines) + visual(Makie.Text))
1 Like