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)
}

Jennifer Jahncke
Jennifer Jahncke
Postdoctoral Scholar

I am a neuroscientist studying how brain cells form and maintain connections.

Related