A dumbbell plot using Veusz

Maybe I’ve missed a trick and there’s a better way. But …

Start with the two columns of data — they could be before and after, left and right, whatever.

Colour Jim’s jellybeans Jane’s jellybeans
Blue 8 24
Green 24 19
Orange 13 19
Pink 9 13
Red 19 9
White 19 8
Yellow 8 8

Now, we make a copy in the same spreadsheet, and paste in transposed. Then we add in some y values for where the lines are going to go; we have 7 colours, so we’ll have 7 y values. I am giving them names like Bluey (blue y value). We can do that using the concat() function (if ‘Blue’ is in F1, then our new cell =concat(f1,”y”)), if working in Excel. An ordinal column of 1–7 is handy too. So now we have (yes, I know this spills off the page; meh):

Ordinal Colour Jim’s jellybeans Jane’s jellybeans Blue Green Orange Pink Red White Yellow Bluey Greeny Orangey Pinky Redy Whitey Yellowy
7 Blue 8 24 8 24 13 9 19 19 8 7 6 5 4 3 2 1
6 Green 24 19 24 19 19 13 9 8 8 7 6 5 4 3 2 1
5 Orange 13 19
4 Pink 9 13
3 Red 19 9
2 White 19 8
1 Yellow 8 8

After we export that from the spreadsheet (gnumeric, Excel, Calc, whatever) as a CSV file, we are ready to plot the graph in Veusz.

Start Veusz. (https://veusz.github.io/) and import the data, and name your Veusz file.

First, we plot 2 line graphs, but vertically. This is easy in Veusz.

Add an xy plot to graph1.

The x data will be Jim’s jellybeans and the y will be Ordinal. (Reverse of what you might expect.)

Now, we can turn off the lines and set the points to be whatever we want, using the Veusz Formatting controls. 8pt is a good dot size.

Then, we set the x and y axis limits. I’m setting x to be 0 to 25 and y to be 0.5 to 7.5. And y is of Mode ‘Labels’, which makes the numbers go away. x has the axis label ‘Number of jellybeans’.

Plot the Jane data in the same way, but in a different colour. Simplest is to copy the first plot and change only colour and data.

For one of the plots, we add labels in the Properties window. Colour column gives the labels, obviously. But we turn off the labelling of the data points, which just leaves the labels on the axis. Also turn off ticks on the colour axis — it is non-numerical.

Add the key at the bottom and set the Key text for each series. (This is not a tutorial on using Veusz in general, so I’m not doing all these steps in detail; hunting around in the GUI usually gets you there. It’s what GUIs are for.)

Now we need the lines between the dots; this is where the other lot of data comes in. We just add more xy plots, each with just a pair of points of the correct height (Bluey etc). So for example we plot Bluey vs Blue, and so on. Again, make one plot, copy it and change the data. 5pt thick line looks ok. Please yourself.

Now we are essentially done, but I am going to colour the lines according to which one is bigger for that colour, Jim or Jane. (I do this manually, but keep in mind you can select several objects and format them all at once [eg to change font, colours etc].) So light blue bars mean Jim had more of that colour and darker bluish-purple means Jane had more of that colour. Here is the result:

Dumbbell plot drawn in Veusz
Same data plotted with offsets

For yellow, they are superimposed and we only see one dot; this could be considered a bad thing, but is typical of these sorts of plots. A little vertical offset could make the dot below a little visible, at the cost of some inconsistency with how the other series are presented; whatever looks good to you. For example, if we create a second Ordinal series (Ordinal2) and plot Jim against Ordinal and Jane against Ordinal2, then we can change the ordinal value against the Yellow number; one can be 0.95 and the other 1.05, say. We’d have to unlink Ordinal, or edit it in the CSV, but we might not want to put manipulations of data purely for plotting purposes in a CSV that notionally at least should only have correct data in it, so I prefer to unlink.

And here is the Veusz script for the plot without the offset; it reads in the data (from dumbbell.csv — if it is in the expected place).

# Veusz saved document (version 3.4)
# Saved at 2023-02-03T03:30:20.515271

SetCompatLevel(1)
AddImportPath('G:\\Content\\Resources')
ImportFileCSV('C:/Users/USERNAME/Desktop/jb/dumbbell.csv', linked=True, numericlocale='en_AU')
Set('colorTheme', 'default-latest')
Set('StyleSheet/axis-function/autoRange', 'next-tick')
Add('page', name='page1', autoadd=False)
To('page1')
Add('graph', name='graph1', autoadd=False)
To('graph1')
Set('hide', False)
Set('leftMargin', '2.0cm')
Set('rightMargin', '0.5cm')
Set('topMargin', '0.2cm')
Set('bottomMargin', '2.8cm')
Set('Border/hide', True)
Add('axis', name='x', autoadd=False)
To('x')
Set('hide', False)
Set('label', 'Number of jellybeans')
Set('min', 0.0)
Set('max', 25.0)
Set('autoMirror', False)
Set('outerticks', True)
Set('Label/font', 'Open Sans Medium')
Set('TickLabels/font', 'Open Sans Medium')
To('..')
Add('axis', name='y', autoadd=False)
To('y')
Set('min', 0.5)
Set('max', 7.5)
Set('mode', 'labels')
Set('autoMirror', False)
Set('direction', 'vertical')
Set('Label/font', 'Open Sans Medium')
Set('TickLabels/font', 'Open Sans Medium')
Set('MajorTicks/hide', True)
Set('MinorTicks/hide', True)
To('..')
Add('xy', name='xy1', autoadd=False)
To('xy1')
Set('markerSize', '8pt')
Set('xData', "Jim's jellybeans")
Set('yData', 'Ordinal')
Set('key', 'Jim')
Set('PlotLine/hide', True)
Set('MarkerLine/hide', True)
Set('MarkerFill/color', '#55aaff')
Set('Label/font', 'Open Sans Medium')
To('..')
Add('xy', name='xy2', autoadd=False)
To('xy2')
Set('markerSize', '8pt')
Set('xData', "Jane's jellybeans")
Set('yData', 'Ordinal')
Set('key', 'Jane')
Set('labels', 'Colour')
Set('PlotLine/hide', True)
Set('MarkerLine/hide', True)
Set('MarkerFill/color', '#5555ff')
Set('MarkerFill/transparency', 0)
Set('Label/font', 'Open Sans Medium')
Set('Label/hide', True)
To('..')
Add('key', name='key1', autoadd=False)
To('key1')
Set('hide', False)
Set('Text/font', 'Open Sans Medium')
Set('Background/color', 'transparent')
Set('Border/color', 'foreground')
Set('Border/width', '12pt')
Set('Border/hide', True)
Set('horzPosn', 'manual')
Set('vertPosn', 'manual')
Set('keyLength', '8mm')
Set('keyAlign', 'centre')
Set('horzManual', 0.0023007246376811788)
Set('vertManual', -0.22710069444444445)
Set('marginSize', 0.0)
Set('columns', 2)
Set('symbolswap', False)
Set('orderswap', False)
To('..')
Add('xy', name='xy3', autoadd=False)
To('xy3')
Set('xData', 'Orange')
Set('yData', 'Orangey')
Set('hide', False)
Set('PlotLine/color', '#5555ff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy4', autoadd=False)
To('xy4')
Set('xData', 'Green')
Set('yData', 'Greeny')
Set('hide', False)
Set('PlotLine/color', '#55aaff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy5', autoadd=False)
To('xy5')
Set('xData', 'Pink')
Set('yData', 'Pinky')
Set('hide', False)
Set('PlotLine/color', '#5555ff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy6', autoadd=False)
To('xy6')
Set('xData', 'Red')
Set('yData', 'Redy')
Set('hide', False)
Set('PlotLine/color', '#55aaff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy7', autoadd=False)
To('xy7')
Set('xData', 'White')
Set('yData', 'Whitey')
Set('hide', False)
Set('PlotLine/color', '#55aaff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy8', autoadd=False)
To('xy8')
Set('xData', 'Yellow')
Set('yData', 'Yellowy')
Set('hide', False)
Set('PlotLine/color', '#55aaff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
Add('xy', name='xy9', autoadd=False)
To('xy9')
Set('xData', 'Blue')
Set('yData', 'Bluey')
Set('hide', False)
Set('PlotLine/color', '#5555ff')
Set('PlotLine/width', '5pt')
Set('MarkerLine/hide', True)
Set('MarkerFill/hide', True)
To('..')
To('..')
To('..')

There are recipes for doing this in Excel, butI am more and more using Veusz.

Author: Darren

I'm a scientist by training, currently working as a writer, trainer and editor.

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.