How to make multi-panel plots?

I want to make multi-panel plots in Pumas, but I am looking for something simple that can be reproduced by someone else on a different dataset. The dataframe can be thought of as having three columns: id, time, dv_ipred; where id is the faceting column, time is the x-axis and dv_ipred is the y-axis.
I looked at the AlgebraOfGraphics piece of code:

f = data(df) * mapping(:time, :dv_ipred, layout=:id => nonnumeric)

However, if there are any missing rows in dv_ipred it just prints the column out like a string in the plot even though it is type of Float64. AoG is very constrained and does not provide lot of flexibility.

So, I tried something in CairoMakie but the code (attached) got long very quickly. Would appreciate if you have any better ideas of doing this.

unique_subjects = unique(

num_subjects = length(unique_subjects)
num_columns = Int(ceil(sqrt(num_subjects)))
num_rows = Int(ceil(num_subjects/num_columns))

resolution = (1000,1000)
f = Figure(; resolution)
id_counter = 1
for (row, col) in Base.product(1:num_rows, 1:num_columns)
    if id_counter <= num_subjects
        a1 = Axis(f[row, col], title="ID = " * string(unique_subjects[id_counter]))
        subject_df = filter(x -> == unique_subjects[id_counter], df)
        lines!(a1, subject_df.time, subject_df.dv_ipred, color=:black)
        id_counter += 1
plottitle = Label(f[0, :], "PK Profiles", textsize = 30)
yaxis_lab = Label(f[:, 0], "Concentrations", rotation = pi/2, textsize=20)
xaxis_lab = Label(f[(num_rows+1):(num_rows+2), :], "Time", textsize=20,
                padding = (0, 0, 0, resolution[1]/20))

Hi @Rahulub3r, AlgebraOfGraphics doesn’t automatically handle missing values and so will treat the column as nonnumeric data when plotting. Using dropmissing to remove the missing values from that column with data(dropmissing(df, :dv_ipred)) should be sufficient to treat the column’s data as numeric instead.

Thank you for your response @Michael . AoG shows the x-axis and y-axis separately for each plot. I want to do like a scales=“free” or scales=“free_x” kind of thing to not have each sub-plot show me an axis with title and labels.

The current version of AlgebraOfGraphics that we provide with Pumas does not provide an out-of-the-box handling of faceted labels. Once we ship a newer version of AlgebraOfGraphics then it will provide that feature automatically. Some amount of what you’re after may be achieved by the following:

fg = 
		data(dropmissing(df, :dv_ipred)) *
		mapping(:time, :dv_ipred; layout = :id => nonnumeric);
		axis = (; xlabel = "", ylabel = ""),
Label(fg.figure[:, 0], "Concentrations"; rotation = pi/2)
Label(fg.figure[end+1, 2:end], "Time")
Label(fg.figure[0, 2:end], "PK Profiles")
1 Like

Wonderful. Thanks for your response Michael!