I have been plotting data from local traffic flows in VagaLite,jl in Pluto. Most of this involves simple line or scatter plots of numerical data stored in dataframes. When I want to show plots side by side I plot data from different columns in a single dataframe side by side by piping the data from the dataframe thus:
df |> [@vlplot(:point, x=:a, y= :b, etc) @vlplot(:point x=:c, y=:d,etc)],
This gives a single plot object with the two different plots properly scaled and formatted, which can be saved as a single file.
However needing to plot from different dataframes where piping isn’t feasible I tried this format to get a single plot, as was suggested elsewhere: [@vlplot(data= df1, :point, x=:a, y=:b, etc) @vlplot(data=df2, :point, x=:a1, y= :b 1, etc)].
This does give a single plot object with the x axes formatted correctly but with the y axes were inverted i.e going from higher to lower values.
Inserting a comma between the two @vlplot yields two properly formatted single plots, needing to be saved separately, rather than a single plot object. I have replicated this behaviour in the repl and vscode, and with model data just in case the downloaded data was corrupted. I am using Julia-1.9.4 with Dataframes v1.6.1 and VegaLite v2.6.0. If there is a better way to obtain the combined plots I’d like to discover it as most of the examples of combined plots in tutorials all appear to come from using single datasets.
In Julia [A, B, C,...]
creates a one-dimensional array (aka vector), while [A B C ...]
is a shorthand for the hcat
method (see the manual).
VegaLite.jl must have a specialized hcat
method that concatenates plots horizontally. While if you use the comma notation, then you are simply obtaining a vector of plots.
I’m not sure I understand what you mean with the “y axes were inverted i.e going from higher to lower values.”, but I also find it odd that the format of the plot results different for the [A, B] version as compared to the [A B] version.
Feel free to give it a try to Deneb.jl and let me know if you also have that inconsistency there. You can produce your plot via:
using Deneb
chart1 = Data(df1) * Mark(:point) * Encoding(:a, :b)
chart2 = Data(df2) * Mark(:point) * Encoding(:c, :d)
[chart1 chart2]
More documentation about concatenation in Deneb.jl here.
Hi Bruno, Thanks for getting back to me on this. To clarify the inverted axes issue the [A B] plot gives the plots plotted upside down with the y axis running from 2000 t0 zero, whereas plotting normally it runs from 0 to 2000, whilst the x axis remains at a constant 0 to 100. However with the [A, B] format everything plots properly. I’ll try Deneb.jl when I get a chance and let you know what happens. Best Wishes, Jeff
Hi Bruno, I have finally got round to experimenting with the porblem with VegaLite that I have. I’ve simplified the data and tried using Deneb to see if that improved things. The problem I was having was the y axis in the plots reversing from low to high when the plots were placed in a combined figure. everything was fine if plotted singly.
In Deneb using the protocol below, taken from your email and having looked at the gallery, this reversal happened even in single figures. In VegaLite I can get the figures I want but only when I pipe the data from the dataframe. I have pasted in the code I used in the experiments below if you want to see the problem. Incidentally I really like the syntax of and figures produced by Deneb. I do hope I’m not doing anything stupid.
using Deneb, DataFramesMeta
#make up the dataframes
df= DataFrame(
A= [1,2,3,4,5,6],
B= [2,4,6,8,10,12]
)
df2= DataFrame(
A=[1,2,3,4,5,6],
C=[3,6,9,12,15,18]
)
#Trying Deneb
chart1 = Data(df) * Mark(:point) * Encoding(:A, :B)
chart2 = Data(df2) * Mark(:line) * Encoding(:A, :C)
#Both charts had inverted y axes
#As did the combined plot
[chart1 chart2]
#Check VegaLite
using VegaLite
p3= @vlplot(data=df, :point, x=:A, y=:B)
p4 = @vlplot(data=df2, :point, x=:A, y=:C)
#both plots OK but combined as below inverted yaves
[p3 p4]
hcat(p3, p4)
combine the two dataframes
df5 = innerjoin(df, df2, on= :A)
#Trying this fails
[@vlplot(data=df, :point, x=:A, y=:B) @vlplot(data=df2, :point, x=:A, y=:C)]
#And so does this
[@vlplot(data=df5, :point, x=:A, y=:B) @vlplot(data=df5, :point, x=:A, y=:C)]
#Now pipe the data to plot and bingo we get what we want
df5 |> [@vlplot(:point, x=:A, y=:B) @vlplot(:line, x=:A, y=:C)]
#Why does only piping the data work??
If you don’t explicitly specify a type for your encodings, VegaLite defaults to the ordinal
type, which doesn’t guarantee any particular order. I suggest you use a quantitative
type for your encodings. You can find more information about VegaLite’s encoding types here. With Deneb.jl you can try the following (see this section to learn more about Deneb’s encoding shortcuts):
chart1 = Data(df) * Mark(:point) * Encoding("A:q", "B:q")
chart2 = Data(df2) * Mark(:line) * Encoding("A:q", "C:q")
[chart1 chart2]
Alternatively you could still use a nominal
or ordinal
type and specify a particular sorting (more here), but I would recommend to use “quantitative” types for quantitative data visualizations.
Bonus tip: you can use markdown notation in discourse to make pieces of code more legible and help others read your posts. For inline code you can wrap things with a single `, and triple ``` for code blocks.
HI Bruno, Thanks for the help. You were right setting the input types fixed the problem. I knew I was being stupid and had missed something. Best Wishes, Jeff