Plots.jl - Plot groups of data on different subplots

Consider this sample data:

using DataFrames, Plots, Random

sample_data = DataFrame([rand(10), sample(['A', 'B', 'C'], 10)], ["value", "group"])
10×2 DataFrame
 Row │ value     group 
     │ Float64   Char  
─────┼─────────────────
   1 │ 0.247725  C
   2 │ 0.638047  A
   3 │ 0.644689  A
   4 │ 0.285569  A
   5 │ 0.29109   B
   6 │ 0.719382  C
   7 │ 0.208312  C
   8 │ 0.405915  B
   9 │ 0.6137    B
  10 │ 0.129875  A

I can easily plot this data grouped by the group column in different colors within the same plot using:

 plot(sample_data.value, group=sample_data.group)

different_colors

But if I want to plot the groups of data over different subplots, the shortest option I’ve found so far is this one:

plots = []
for group_data in groupby(sample_data, :group)
    push!(plots, plot(group_data.value))
end

plot(plots...)

different_subplots

This seems a bit overly complicated. I’m still new to Julia, so atm I don’t know if this can be improved. Python for example has within the seaborn package sns.plot(sample_data, x='value', col='group'). But I couldn’t find something similar for Plots.jl yet.

Perhaps someone knows how my solution to plotting datafarme groups over different subplots can be shortened or put into a similar one-liner as above.

EDIT: I already found a slightly better solution. List comprehensions of course!

plot([plot(group_data.value) for group_data in groupby(sample_data, :group)]...)

I would have suggested the list comprehension as well - I don’t know of anything inbuilt in Plots (although that doesn’t mean it doesn’t exist!), so unless others chime in you can consider opening an issue over at the Plots.jl repo.

FWIW I don’t think it’s necessary to add this feature given how short and explicit the solution based on composing existing building blocks (list comprehension, splatting, groupby in DataFrames) is.

I also don’t think it’s necessary to add that feature. With the list comprehension method you can also easily change the arrangement using the layout argument, or add multiple list comprehensions or other plot calls easily. So it is quite flexible.

Only drawback I can see is that the code might get a bit overwhelming when adding different formatting and titles etc. for each plot.

Agreed - I think at this point you might be better off with the loop where you can be more explicit about things like this:

for (n, g) ∈ pairs(groupby(sample_data, :group))
    push!(plots, 
        plot(group_data.value, label = $(n.group), ...)
    )
end

FWIWthere is a built in version in Statsplots:

julia> using StatsPlots

julia> @df sample_data plot(:value, group = :group, layout = 3)

1 Like