Chord Diagrams: Religious Composition of Romantic Partners
Also known as “radial network diagrams”, chord diagrams are useful for representing connections between groups (“nodes”). The nodes are circularly arranged and relationships are represented using “chords” connecting two nodes. The chords can carry directional relationships or non-directional relationships. This is a very visually pleasing way to represent relationships and is a powerful method of visualizing large datasets. There is, however, a steep learning curve when it comes to creating chord diagrams. Below I will outline two methods, first I will use the circlize
package to create a static diagram and then I will use the chorddiag
package to create an interactive diagram. For more information on how to build chord diagrams using circlize
, see
Circular Visualization in R by Zuguang Gu (the creator of the circlize
package). The documentation for circlize
can be found
here. There is some useful information on the
R Graph Gallery chord diagram page (more
here and
here). For more information on the chorddiag
package, you can find the documentation
here. For an explanation of all of the variables you can customize, see
additional documentation here.
{width=80%}
The Data: How Couples Meet and Stay Together
The datset is from Stanford’s How Couples Meet and Stay Together research project. The dataset contains responses from 4,000 individuals and describes the relationships in their lives. The researchers then followed up on the respondents over several years to track their relationships over time. There are 300+ variables in this dataset. Here I focused on the religious identities of the couples surveyed.
A glimpse of the data: What are the religious compositions of partners?
Respondent | Partner | Count |
---|---|---|
Baptist | Baptist | 224 |
Baptist | Buddhist | 1 |
Baptist | Catholic | 112 |
Baptist | Jewish | 2 |
Baptist | Mormon | 7 |
Baptist | Muslim | 3 |
Baptist | None | 72 |
Baptist | Other | 9 |
Baptist | Other Christian | 67 |
Baptist | Pentecostal | 26 |
Baptist | Protestant | 147 |
Buddhist | Catholic | 5 |
Buddhist | None | 7 |
Buddhist | Other | 1 |
Buddhist | Other Christian | 1 |
Buddhist | Protestant | 4 |
Catholic | Catholic | 415 |
Catholic | Eastern Orthodox | 5 |
Catholic | Hindu | 1 |
Catholic | Jewish | 40 |
Representation Description
One of the variables in the dataset is the religion of the responent and their partner when they were 16. Each node in my chord diagram represents a religion. Chords connecting the nodes illustrate the religion of the respondent on one end of the chord and their partner on the other end of the chord. In many cases the respondent had the same religious identity as their partner, in which case the chord loops back on itself and looks more like a bump. The thickness of the chord corresponds to the number of partners of that particular religous identity composition. Each node is assigned a color to aid in interpretation. The color of a chord corresponds to the node from which the chord stems from. Transparency was used to aid in the perception of overlapping chords.
How to interpret
Chord diagrams are best used to communicate broad concepts rather than specifics. From this representation it becomes immediately apparent that a very common religious pairing occurs between Catholics and Protestants. It is also common for partners to share the same religious identity. A side effect of this representation is that we can learn something about the religious composition of the participants that were surveyed; most respondents were Protestant, Baptist, or Catholic.
Presentation Tips
Many aspects of the diagram can be customized if you’re using the circlize
package. The package creator has an entire book on the topic available online:
Circular Visualization in R. You can indicate directionality of the chords using arrowheads, which I disabled in my diagrams. You can also change the appearance of within-node chords such that they look like little bumps instead of a chord turned in on itself, which I find easier to understand. Depending on the level of detail that you are trying to convey with your diagram, you might opt to eliminate smaller chords by setting a threshold for chord thickness.
Variations and Alternatives
Another way to represent relationships between groups is through a Sankey or Alluvial diagram. These are very similar to chord diagrams except that the relationship is conveyed through a line connecting two columns and can thus show a larger number of relationships due to the linear layout. Alternatively, network diagrams and arc diagrams can also be useful for communicating relationships.
The Chord Diagrams
Static Chord Diagram Using circlize
# Define colors
gridcolors <- c(Baptist = "#F8766D",
Buddhist = "#E18A00",
Catholic = "#BE9C00",
`Eastern Orthodox` = "#8CAB00",
Hindu = "#24B700",
Jewish = "#00BE70",
Mormon = "#00C1AB",
Muslim = "#00BBDA",
None = "#00ACFC",
Other = "#8B93FF",
`Other Christian` = "#D575FE",
Pentecostal = "#F962DD",
Protestant = "#FF65AC")
chordcolors <- religion_16_summary %>% mutate(Color = case_when(Respondent == "Baptist" ~ "#F8766D",
Respondent == "Buddhist" ~ "#E18A00",
Respondent == "Catholic" ~ "#BE9C00",
Respondent == "Eastern Orthodox" ~ "#8CAB00",
Respondent == "Hindu" ~ "#24B700",
Respondent == "Jewish" ~ "#00BE70",
Respondent == "Mormon" ~ "#00C1AB",
Respondent == "Muslim" ~ "#00BBDA",
Respondent == "None" ~ "#00ACFC",
Respondent == "Other" ~ "#8B93FF",
Respondent == "Other Christian" ~ "#D575FE",
Respondent == "Pentecostal" ~ "#F962DD",
Respondent == "Protestant" ~ "#FF65AC"))
chordcolors <- chordcolors$Color %>% unlist()
# Create the chord diagram
circos.clear()
par(mar = c(0, 0, 0.5, 0)) # left, right, top, bottom: add margin around circle
circos.par(cell.padding = c(0, 0, 0, 0),
gap.degree = 1,
canvas.ylim = c(-0.6, 0.8), # change the y limits of the canvas
canvas.xlim = c(-1.1, 1.1)) # change the x limits of the canvas
chordDiagram(religion_16_summary,
transparency = 0.5,
grid.col = gridcolors,
link.lwd = 0.5, # border line width
link.lty = 1, # border line type
link.border = chordcolors, # border line color
link.sort = TRUE, link.decreasing = TRUE, # Control the positioning of the sector links to minimize crossings
self.link = 1, # Make self-links humps, not chords ( = 2 for chords)
annotationTrack = "grid", # We'll plot the labels later
annotationTrackHeight = 0.02, # Height for the annotation "grid"
preAllocateTracks = 1, # Pre allocate a track and later the sector labels will be added
directional = FALSE, # There is no directionality to the connections
order = religion_16_summary$Respondent) # Order according the the respondent first, partner second
# Since each respondent is a sector, we need to use `draw.sector` to add annotation grids for regions which go across several religions
first = tapply(religion_16_summary$Respondent, religion_16_summary$Partner, function(x) x[1])
last = tapply(religion_16_summary$Respondent, religion_16_summary$Partner, function(x) x[length(x)])
for(i in seq_along(first)) {
start.degree = get.cell.meta.data("cell.start.degree", sector.index = first[i], track.index = 1)
end.degree = get.cell.meta.data("cell.end.degree", sector.index = last[i], track.index = 1)
rou1 = get.cell.meta.data("cell.bottom.radius", sector.index = first[i], track.index = 1)
rou2 = get.cell.meta.data("cell.top.radius", sector.index = last[i], track.index = 1)
draw.sector(start.degree, end.degree, rou1, rou2, border = NA, col = "white")
}
# Since default text facing in `chordDiagram` is fixed, we need to manually add text in track 1
for(si in get.all.sector.index()) {
xlim = get.cell.meta.data("xlim", sector.index = si, track.index = 1)
ylim = get.cell.meta.data("ylim", sector.index = si, track.index = 1)
circos.text(mean(xlim), ylim[1], si, facing = "clockwise", adj = c(0, 0.5),
niceFacing = TRUE, cex = 1.25, col = "black", sector.index = si, track.index = 1)
}