Viz for Social Good: Association for the Prevention of Torture

volunteer project
VFSG
D3.js
R
Author

Gabrielle M. Schroeder

Published

December 5, 2024

I created these visualisations for the November 2024 Viz For Social Good (VFSG) project with the Association for the Prevention of Torture (APT).

APT asked VFSG volunteers to visualise data on several legal measures, such as United Nations standards, that help prevent torture. For each legal measure, they provided data on whether each of 196 tracked states (i.e., sovereign entities such as countries) have implemented each measure and, if so, the year the state implemented it.

APT emphasised that the visualisations needed to be positive and celebrate progress. They also wanted to provide opportunities to compare legal measures, global regions, and states, but without “naming and shaming” regions or states that hadn’t made as much progress. They sought interactive visualisations to add to their website, but also wanted the option to use them in a static form for publications.

Visualisations

The webpage with the interactive visualisations is here.

Screenshots

Different regions

I also created a stand-alone version of the “all regions” view that fills the available vertical space:

Different legal measures

Data decisions

To visualise progress over time, I computed the total number of states that had implemented each measure as of each year. This approach focuses on the cumulative progress that has been made, rather than when the legal measures were implemented in each state.

I also combined APT’s two “National Preventive Mechanism” (NPM - a type of oversight system) measures into a single measure. NPMs take multiple stages to implement, and APT provided the date each state completed the first step (“designating” an NPM) and the last step (when the NPM becomes “operational”). I used this data to calculate the number of countries with a designated and operational NPM, as opposed to a designated only NPM, and treated these statuses as different levels of the same legal measure. Compared to reporting the total number of designated NPMs (regardless of whether they are operational or not), this approach allows us to easily see 1) how many designated NPMs need to become operational, and 2) see designated-only NPMS convert to fully operational NPMs over time.

Consolidating this data left me with a total of seven different legal measures, two of which could also be partially implemented.

Design decisions

Overview

I found the dataset slightly overwhelming at first due to my unfamiliarity with the legal measures and technical terms. As such, I decided to start by introducing and summarising these different measures using accordion panels. These panels are collapsed by default, which avoids bombarding the audience with too much information at once.

I also asked APT if they had a preferred way to group the different measures. They provided three different categories, which really helped me build a mental framework for understanding this data. I therefore used this same organisation in the introduction.

The subsequent two visualisations are then designed to give overviews of the progress made over time, with the first giving a high-level overview (number of states that have implemented each measure) and the second breaking down that data at the level of different states. I let interactivity take a back-seat in these visualisations - partly because of my skill gap (this was my first D3.js visualisation!), but also because I wanted the main messages to be readily accessible in a static format.

While this post is about data vis, I’m also a bit of an English language nerd, so I’ll quickly point out a change I made to the legal measure terms: turning the nouns back into verbs (e.g., “prohibition” to “prohibit”, “ratification” to “ratify”). This verb-to-noun transformation is called “denominalisation”. The reverse - nominalisation - is useful in moderation or certain contexts (“(de)nominalisation” itself is a noun form of a verb!), and it’s often necessary in formal or legal documents. However, nominalisations can make writing less approachable, less animated, and more jargony. Some people have even labelled them “zombie nouns” because of their potential to suck the life out of writing. Since this work was designed for a general audience, I went with the verb forms where possible, which had the added visualisation benefit of shortening my labels, too!

Colours

Throughout the webpage, I use colour to encode the different legal measures. To reinforce the legal measure categories, I used a different hue for each one: blue for the international standards, yellow for domestic law, and red for oversight systems. Lighter and darker shades of each hue then distinguish the legal measures within each category. These colours are based on APT’s blue and red/pink branding colours, with the addition of a complementary shade of yellow to provide three hues for the three categories.

Stacked bar chart

For the first visualisation, I use a stacked bar chart to show the total number of states that have implemented each legal measure versus time, with each bar colour corresponding to a different legal measure. This approach makes it more difficult to see trends in the individual measures, but emphasises the total number of commitments that have been made towards preventing torture, which was the key message I wanted to convey.

I considered using an area chart instead of a bar chart, but decided on the latter to highlight the year-to-year changes. The bars also allowed me to use styling, such as gradients and selectively rounded edges, to give a layered effect to the visualisation. My aim was to give the impression that these legal actions are building a physical barrier to torture.

I also added region filters to show the progress within each region, with the height of the y-axis proportional to the number of states to make it easier to compare region-level progress. For example, it’s easy to see that Europe’s bar chart is noticeably higher. The reference bar and text on the left provides the total number of states and the corresponding bar length.

Radial bar chart

The second visualisation breaks down this progress to the level of states by showing when each state implemented each legal measure. My idea for a radial layout originated from my original plan, which was to show all the legal measures as different circles in one plot. However, I quickly realised this wouldn’t fit a standard screen width and instead added a dropdown filter for the different measures. Even in this format, I decided to keep the radial layout as a more compact representation than a horizontal or vertical chart. The trade-off is that the radial layout makes exact comparisons more difficult, but my aim was to communicate general trends, rather than precise differences between countries and regions.

I added gaps between the different regions to emphasise region differences, then put the states ordered alphabetically within each region, which makes states easier to find and keeps the order the same across indicators. There’s a simple tool-tip that reveals the name of each state when you hover over that bar (or gap, in the case of states that haven’t implemented a measure).

Technical details

Tools

My goal for this project was to finally learn D3.js (not to mention Javascript). I first used my preferred data wrangling language, R, for data exploration and some initial transformations (like creating my custom NPM measure), then created the webpage and visualisations using HTML, CSS, Javascript, and D3.js. I wouldn’t have made it nearly as far without the newly released edition of D3.js in Action for guidance.

All my code is available in a GitHub repo, but I’ll caveat that the code reflects both my inexperience and the project time constraints!

Technical tricks

I face a few technical challenges when implementing my planned design, and I learned that sometimes the easiest approach for creating custom designs is modifying the underlying data. When I say “modify”, I don’t mean changing the actual displayed values, but rather adding duplicate or extra entries that are used solely for styling or layouts.

I first used this approach for the styling of the striped bars in the stacked bar chart. These bars need both a subtle gradient (to match the styling of the other bars and give the layered effect) and a pattern fill (to indicate that the measures were partially implemented). I spent hours trying to figure out how to combine these styles before realising I could just duplicate the corresponding entries in the data array. I used the first copy to add the stripe fill, then made the second copy (which I labelled as a duplicate) to add another, partially transparent element in the same location, allowing the stripes to be visible underneath.

Meanwhile, in the radial bar chart, I wanted to add gaps to separate the different regions. To do so, I ensured the data was sorted by region, then detected the locations where the regions changed and added filler entries between them. As above, these additional entries were clearly labelled so I could detect them and make them invisible, leaving only the actual data displayed. I also gave the entries in each gap a unique “region” name (such as “spacer1”, “spacer2”, etc.). This approach allowed me to add a border around each region by making a donut chart of the number of states in each region - including in my spacer regions. I added this donut chart as a background, again hiding the spacer regions so only the actual data was visible.

Developing the donut chart of the regions.

Same donut chart with the “spacer” regions hidden.

The final technical trick that I’ll highlight was rotating the stripe fill in the radial bar chart. This rotation is needed to maintain consistent angles between the stripes and the bar edges - otherwise, the angles would be distractingly inconsistent, with stripes approximately parallel to the bar length in the worst-case scenarios. I had already computed the mapping from country to angle for the bars themselves, and could use the same angles to rotate my stripe pattern.

Possible improvements

I ran out of time to implement everything I wanted to, and in particular had less time to work on the radial bar chart. Here’s some of the improvements I’d focus on next:

  • Improving accessibility (e.g., ensuring the key data can be read using a screen reader).
  • Adding a tooltip for the bar chart.
  • Adding a timeline of major events (e.g., the dates different legal measures were adopted by the UN) to the bar chart x-axis and annotating these years on the relevant radial bar charts.
  • Improving the tooltip for the radial bar chart to provide more information (e.g., dates) and visually indicate which state is being being hovered over.
  • Experimenting with short labels or tick marks/dots to mark each state (which is especially important for marking states that haven’t implemented any measures).
  • Adding a toggle to re-order the radial bar chart by implementation dates, rather than alphabetical order.
  • Replacing the text explanation of the stripe pattern with a legend.
  • Creating a state-level visualisation or table that indicates all of the legal measures that the state has implemented.

In-progress images (and accidental art)

Early sketches.

I almost always end up sketching out some calculations, too.

Some data exploration in R.

Initial encoding as step chart, demonstrating 1) the importance of the bar styling for this data, and 2) the ugly early stage when you just need to trust in the process.

Very spikey result produced by an early attempt at a custom bar shape.

Initial custom curved bars and learning how to define gradients.

Laying out an initial title, subtitle, and labels

Experimenting with the gradient. A vertical gradient doesn’t work well - it makes it look like each series extends behind the others to the base of the graph, giving the impression of a taller bar - and thus a larger value.

Learning how to create a striped fill; this result makes me want to do a monochromatic visualisation at some point.

Now stripes with different colours.

Realising it’s difficult to distinguish neighbouring striped bars.

Experimenting with adding a border around striped bars to make the colours and edges clearer - it achieved that goal, but made these bars very salient (the opposite of the intended effect).

Moving on to the radial plot - a quick check that the radial layout works.

I also quickly checked a vertical layout to confirm, as expected, the chart would need to be really tall to fit all the countries - the bars have to be very skinny to fit in this space.

Initial radial layout without the region grouping.



License: CC BY-NC 4.0