Homework 4: Playfair Reconstruction

Author

Megan Witzenburg

Published

September 24, 2025

Part 1: Critique

This first part is a critique of Playfair’s data visualization.

Playfair’s graph features many aspects that work well to display the information. The use of bars to represent the population of each country was wise. It is relatively simple to notice where each bar ended, so it was clear how populated each country was. It was also useful to have the taxation be a bar, because it also allowed for easier interpretation of exactly how much taxation was in each country. The use of color for Power (and different hues) signals our brains that they’re separate categories and allows for easier comparison between splits of powers between different countries.

One of the first things I noticed was a lack of tick marks on the x axis and a lack of variable labels on the x and y axes. It took me much longer than it should have to figure out what was actually being displayed because nothing was labelled clearly. The use of Area for size of bubbles was an okay choice, but it wasn’t great. It’s easy to see the difference between the super large circles and the smaller ones, but once you get further to the right on the x axis, all of the bubbles look the exact same size. I can tell how much smaller they are because they’re labelled, but I can’t see the difference, which should be the point if a variable is mapped to area.

I also don’t think the diagonal lines between the columns of population and taxation are very helpful. Though they add wonderful motion to the visual and are meant to show how much or little people are being taxed in each country, it’s not immediately intuitive. The color of the taxation and population bars is also somewhat deceptive. Though the circles are colored by Power, the bars for population and taxation are also colored. These colors sometimes correspond with the color of the country (ex. population was red, and some country circles are also red), so it’s difficult to decipher if the color of the bars corresponds to different countries (especially for empires split between different countries) or to something else.

I used this resource to help me figure out what was mapped to what: https://m-a.org.uk/resources/PE4LifeofPie.pdf

The graph somewhat communicates what it set out to communicate, but there’s so much going on that I’m not sure what the point exactly was. He communicates the land area of countries really well for the big countries, but it’s hard to see the differences between the small countries. I can tell that taxation differs between countries, sometimes very dramatically. I can also tell that some countries/empires are split among many entities. However, I believe this graph attempts to display too much all at once. All of the data feels muddied and unconnected.

Part 2: ggplot Recreation

library(tidyverse)
Warning: package 'ggplot2' was built under R version 4.4.3
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   4.0.0     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
#install.packages("ggthemes")
library(ggforce)
Warning: package 'ggforce' was built under R version 4.4.3
library(scales)
Warning: package 'scales' was built under R version 4.4.3

Attaching package: 'scales'

The following object is masked from 'package:purrr':

    discard

The following object is masked from 'package:readr':

    col_factor
europe <- read.csv("playfair_european_nations.csv")

europe$Country <- fct_reorder(europe$Country, -(europe$Area))
europe$rad <- sqrt(europe$Area / pi) / (sqrt(europe$Area[1] * pi))
europe |> 
  ggplot() +
  # all of the weird 60/13 multiplying was to try to elongate the x axis and
  #keep the circles looking like circles, not ellipses. 
  geom_circle(aes(x0 = as.numeric(Country) * 60/13, y0 = 0, r = rad * 10, 
                  fill = Power, alpha = 0.7)) +
  # the - (rad * 10) and + (rad * 10) parts are to try to offset the line segments
  # to the edges of the circles. 
  scale_fill_manual(values = c("#b05a4f", "#8ba863")) + 
  geom_segment(aes(x = as.numeric(Country) * 60/13 - (rad * 10), y = 0, 
                   xend = as.numeric(Country) * 60/13 - (rad * 10), 
                   yend = Population), linewidth = 1.25, 
                  color = "#b05a4f", alpha = 0.8) + 
  geom_segment(aes(x = as.numeric(Country) * 60/13 - (rad * 10), y = 0, 
                   xend = as.numeric(Country) * 60/13 - (rad * 10), 
                   yend = Population), linewidth = 0.1, 
                  color = "#3b3b3b", alpha = 0.8) + 
  geom_segment(aes(x = as.numeric(Country) * 60/13 + (rad * 10), y = 0, 
                   xend = as.numeric(Country) * 60/13 + (rad * 10), 
                   yend = Taxation), linewidth = 1.5, 
                  color = "#e4dc8a", alpha = 0.8) + 
  geom_segment(aes(x = as.numeric(Country) * 60/13 + (rad * 10), y = 0, 
                   xend = as.numeric(Country) * 60/13 + (rad * 10), 
                   yend = Taxation), linewidth = 0.1, 
                  color = "#3b3b3b", alpha = 0.8) + 
  geom_segment(aes(x = 0, xend = max(as.numeric(Country) * 60/13 + (rad * 10)),
                   y = 0, yend = 0), inherit.aes = FALSE) +
  geom_segment(aes(x = 0, xend = 0,
                   y = 0, yend = 30), inherit.aes = FALSE) +
  geom_segment(aes(x = as.numeric(Country) * 60/13 - (rad * 10), 
                   y = Population, xend = as.numeric(Country) * 60/13 + 
                     (rad * 10), yend = Taxation), linetype = "longdash", 
                     color = "#3b3b3b") + 
  xlim(0, 60) +
  coord_fixed() + 
  scale_y_continuous(sec.axis = dup_axis(name = "Millions"),
                     breaks = seq(0, 30, 1)) +
  labs (x = " ", y = " ", title = "CHART Representing the EXTENT, POPULATION & REVENUES, of the PRINCIPAL NATIONS in EUROPE, after the DIVISION of POLAND & TREATY of LUNEVILLE.") + 
  theme(text = element_text(family = "serif", colour = "black"), 
        axis.text.y = element_text(colour = "black"), 
        axis.title.y = element_text(colour = "black"),
        axis.title.y.right = element_text(family = "serif", 
                                          colour = "black", size = 10),
        axis.ticks.x = element_blank(),
        axis.ticks.y = element_line(colour = "black"),
        
        axis.line.y = element_blank(
        ),
        axis.text.x = element_blank(),
        plot.title = element_text(size = 9, colour = "black", face = "bold"),
        plot.background = element_rect(fill = "#f2e5d0"),
        panel.background = element_rect(fill="#f2e5d0"),
        panel.grid.major = element_line(color = "#C9B297"),
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.line.x = element_line(colour = "black"),
        axis.line.y.right = element_blank(),
        axis.line.y.left = element_blank(),
        axis.line.x.top = element_line(colour = "black"),
        axis.line.x.bottom = element_blank(),
        legend.position = "none") + 
  geom_text(aes(x = (as.numeric(Country) * 60/13), y = -4, 
                label = str_wrap(Country, 2)), 
            color="black", angle = 90, size = 3) + 
  geom_text(aes(x = as.numeric(Country) * 60/13, y = -0.5, label = Area), 
            color="black", size = 3) 
Warning in geom_segment(aes(x = 0, xend = max(as.numeric(Country) * 60/13 + : All aesthetics have length 1, but the data has 12 rows.
ℹ Please consider using `annotate()` or provide this layer with data containing
  a single row.
Warning in geom_segment(aes(x = 0, xend = 0, y = 0, yend = 30), inherit.aes = FALSE): All aesthetics have length 1, but the data has 12 rows.
ℹ Please consider using `annotate()` or provide this layer with data containing
  a single row.

Note: these are the online resources I used (besides documentation and the book).

To try and understand what Playfair was trying to get at: https://m-a.org.uk/resources/PE4LifeofPie.pdf

To add a secondary y axis (I also later found this in the documentation): https://finchstudio.io/blog/ggplot-dual-y-axes/

Figuring out line types for geom_segment: https://stackoverflow.com/questions/72308711/add-linetype-to-geom-segment-legend

To remember the scale_fill_manual function and how to encode colors to factors: https://stackoverflow.com/questions/75860574/how-do-i-change-the-fill-of-individual-circles-in-ggforcegeom-circle-to-custom

To figure out how to change font face (2): https://www.geeksforgeeks.org/r-language/fonts-in-r/

https://stackoverflow.com/questions/27306650/how-do-i-change-the-text-font-size-and-colour-of-all-the-different-texts-in-the

To hide the x axis: https://www.sthda.com/english/wiki/ggplot2-axis-ticks-a-guide-to-customize-tick-marks-and-labels

How to remove a legend: https://stackoverflow.com/questions/35618260/remove-legend-ggplot-2-2

Adding the extra border lines for the x & y axis: https://stackoverflow.com/questions/76126041/ggplot-any-way-to-only-draw-x-axis-border-starting-from-0

How to change title/text for secondary y axis: https://r-graph-gallery.com/line-chart-dual-Y-axis-ggplot2.html

Remembering the alpha = part of geoms: https://www.statology.org/r-plot-alpha/

Figuring out how to add text to each individual circle without finding x-y coordinates: https://r-graph-gallery.com/233-add-annotations-on-ggplot2-chart.html

For wrapping the text labels of the countries: https://stackoverflow.com/questions/47446259/wrapping-long-geom-text-labels

Part 3: New Data Visualization

neweurope <- europe |>
  select(Country, Population, Taxation, Power) |>
  mutate(poppercent = Population / (Taxation + Population),
         taxpercent = Taxation / (Taxation + Population))

neweurope$poppercent = ifelse(is.nan(neweurope$poppercent), 0 , 
                              neweurope$poppercent)
neweurope$taxpercent = ifelse(is.nan(neweurope$taxpercent), 0 , 
                              neweurope$taxpercent)
ggplot(neweurope, aes(y=taxpercent, fill = Power, x=reorder(Country, -taxpercent))) + 
  geom_col() + 
  scale_fill_manual(values = c("#d3997f", "#8ba863")) + 
  geom_segment(aes(x = 0, xend = 13,
                   y = 0.5, yend = 0.5), linetype = "longdash", 
                  color = "#3b3b3b", inherit.aes = FALSE) + 
  labs (x = "Country", y = "Tax to Population Ratio", 
        title = "CHART Representing the POPULATION & REVENUES, of the PRINCIPAL NATIONS in EUROPE, after the DIVISION of POLAND & TREATY of LUNEVILLE.") + 
  theme(text = element_text(family = "serif", colour = "black"), 
        axis.text.y = element_text(colour = "black", family = "serif"),
        axis.text.x = element_text(colour = "black", family = "serif"),
        axis.title.y = element_text(colour = "black", 
                                    family = "serif", face = "bold"),
        axis.title.x = element_text(family = "serif", 
                                          colour = "black", face = "bold"),
        axis.ticks.y = element_line(colour = "black"),
        axis.ticks.x = element_line(colour = "black"),
        axis.line.x = element_line(colour = "black"),
        axis.line.y = element_line(colour = "black"),
        legend.title = element_text(colour = "black", 
                                    family = "serif", face = "bold", size = 11),
        panel.grid.major = element_line(color = "#C9B297"),
        legend.background = element_rect(fill = "#f2e5d0"),
        panel.grid.minor = element_blank(),
        plot.background = element_rect(fill = "#f2e5d0"),
        panel.background = element_rect(fill="#f2e5d0"),
        plot.title = element_text(size = 9, colour = "black", face = "bold")) + 
        scale_x_discrete(labels = label_wrap(width = 0.5)) 
Warning in geom_segment(aes(x = 0, xend = 13, y = 0.5, yend = 0.5), linetype = "longdash", : All aesthetics have length 1, but the data has 12 rows.
ℹ Please consider using `annotate()` or provide this layer with data containing
  a single row.

Here are more resources I used:

Ordering the columns by size: https://stackoverflow.com/questions/37480949/re-ordering-bars-in-rs-barplot

Adjusting figure sizes: https://www.andrewheiss.com/blog/2022/06/23/long-labels-ggplot/

Text Wrapping: https://www.databrewer.co/R/visualization/3-ggplot2-wrap-long-texts

Changing panel backgrounds within theme(): https://stackoverflow.com/questions/6736378/how-do-i-change-the-background-color-of-a-plot-made-with-ggplot2

More theme things to fiddle with: https://stackoverflow.com/questions/6051542/color-of-gridlines-and-background

https://stackoverflow.com/questions/2678141/how-can-i-suppress-the-vertical-gridlines-in-a-ggplot2-plot

Part 4: Concluding Explanation

I chose to map Taxation (divided by Population) to the height of the bars because that was the main point of the visual. It allows for easy and immediate comparison between countries to see which ones tax their people the most. I chose to map the Power to the color element because it was a 2-category variable (and was mapped to color in the original graph as well). It is appropriate because the red and green denote two different categories, since they’re separate hues.

I decided to organize the bars by descending tax in proportion to population, this way it’s easier to see which countries tax disproportionately. We can actually see that Spain and Portugal both also tax disproportionately, along with Britain (as Playfair pointed out). I added a dotted line at the 0.5 mark to denote when a country’s taxes becomes higher in proportion to its population. I think this was wise because it’s easier to see which countries tax higher.

I wasn’t able to think of a way to incorporate all of the information. I think it would be improved if I could add Area as part of the graph in some way, whether that be through color or some other aesthetic. I used the green and red colors because they matched the colors that Playfair used. However, I think this can tend to be a little deceptive. Usually we perceive green as good and red as bad, so if I was going off of that, I would make the first three bars (over 0.5 tax proportion) red and the rest green to better convey the message.

It appears that the data does support Playfair’s point that Britain taxes unfairly (although it appears a few other countries do as well). We can see that proportional to Britain’s population, Britain’s taxes are highest.