Visualizing Comic Characters’ Genders and Superpowers

How to create a stacked bar chart with tooltips using D3 & React; and a brief discussion on comics, gender and superabilities

Henry Heberle, PhD
Towards Data Science

--

A small piece of the final chart

Summary

1. Visualizing Superabilities and Genders

2. Querying the Comic Data

3. Creating React Components

4. Setting up Tooltips

5. References to learn D3 & React integration

React and D3 are the tools I use here. I point out what are the core parts that make this version different from a regular D3 version, which is based on enter(), exit() and update().

I wrote this article for who knows a bit of D3 and want to code in a React fashion. If you have no idea on how to code using React, I strongly recommend this 100% free interactive course on Scrimba.

This is the GitHub bar chart repository: https://github.com/heberleh/learn-react-d3/.

This is part 2 of my series on Comics Characters:

  1. Create a Marvel Database with SQL and Javascript, the easy way
  2. Visualizing Comic Characters’ Genders and Superpowers [this]
  3. Comparing Marvel and DC with Data Visualization
Legend of Marvel & DC visualization: https://heberleh.github.io/comics-universe/

1. Visualizing Superabilities and Genders

This section first directs you to the interactive bar chart and describe details about the plot. Then, it gives you a brief discussion on abilities and genders of comic characters.

Interactive Stacked Bar Chart

https://heberleh.github.io/learn-react-d3/

My intention was to show the distribution of male, female and other genders among superabilities while showing the superabilities’ popularity. Stacked bar charts is a plausible choice in this case.

Each bar represent one ability. Its size represents the number of characters. All from Wikidata.

Mouse over reveals details about the ability, such as description and numbers.

I have used many colours in this chart. This could be considered clutter if I wanted to focus on some specific information.

For instance, in the bar chart shown in the Marvel & DC visualization, I chose only 2 colors. One is dark, and the other is highlighting abilities that have more non-males than males characters.

Here I used only instances of Comic Character from any Fictional Universe; in the Marvel & DC visualization, I used instances of Fictional Character, and subclasses, from Fictional Universe equals to Marvel/DC.

Interpretation and discussion

When interpreting this plot we need to consider that there is in fact more males than females and other genders in most, if not all, Fictional Universes. We may expect an average between 60% to 70% of characters being male in each Universe. Therefore, it is also expected more males in most of the popular abilities.

On the other hand, we can identify less popular skills where the number of females is greater than the number of males. Among them are force field, phytokinesis, cryokinesis, aerokinesis, elasticity, probability manipulation, retrocognition and bloodbending. Any historical or social fact that can explain it?

Marvel Premier — Dark Phoenix Artist Proof by theopticnerve. Under CC BY-NC-ND 3.0

Very few characters have gender different from male and female.

One gender found in the plot is named agender — check the green bars.

That is the case of Phoenix Force.

Gender, race and other factors are being more discussed than before and authors are more concerned about it.

As an example, Jacques Nyemb discussed some good points on this topic. In the article, he wrote about his comic being relatable:

“I came to a conclusion I didn’t want to arrive to. The readers where white males and my character is a black one.”

Jacques also wrote about his first thought when creating a fictional scientist, a white male:

“… I quickly asked myself why not have a female scientist? A black, middle-aged one at that? Her motives made far better sense in my new story than if I stayed with my original idea.”

For me, and I am not a specialist, any Universe that wants to relate to our reality needs to represent the different people and cultures to become consistent. Creating a diverse fictional universe is to be inclusive and more close to our reality, specially when its audience is the entire world.

2. Querying the Comic Data

To create a plot that shows how many characters have each ability (stacked bar size) and how those numbers are distributed among genders (colors, bars), I queried a table from the Comics Database containing the following information:

  • Character
  • Abilities
  • Gender

To use this database, you just need to download some .js and .json files and import, then you can query using SQL commands. If you want to learn how to query data from Wikidata and create a Javascript database, check the first article. Here is my SELEC command:

After some data manipulation, my data is formed by:

  • labels vector: the genders labels
  • data: one vector for each ability containing a vector of total of characters per gender, indexed according to labels

Example:

I defined that the stacked bar chart component receives as input a Data Model. It contains the data and helper functions to get the labels and totals:

You find the skillsDistributionByGender() complete code here.

3. Creating React Components

After defining my data set, I started creating a simple Bar Chart based on this post and code by Kacper Goliński.

If you did not create any chart using React and D3, you may find it easier to start with a simpler bar chart and then come back to check how I did the stacked one and how I added tooltips.

Kacper also implemented the ResponsiveWrapper that controls the width of the chart based on the width of the visible window.

At this point I consider that you know the create-react-app. If you don’t, search about it or check the course I mentioned at the beginning.

Our final SVG will have two main React components responsible to show the y-axis and the abilities’ labels (<Axes/>) and the stacked bars ( <StackedBars/> ). I set an extra Component to control the tooltips, shown on m ouse over each bar ( <ReactTooltip/>):

There are different approaches to integrate D3 and React.

The first approach is to modularise the App using React and use D3 to control the SVG elements with enter(), update() and exit().

A second approach is to control all the SVG elements using React, which makes more sense to a React application. Therefore, instead of calling .attr('width', 200) we will set it directly to the component or SVG element like in this example:

This code returns the <rect> elements, which we will put inside a <g> to group rectangles of each bar/ability. Thus, we can add it to a function and call it for each ability, as coded here:

This code will create a <g> for each ability and a final <g> with all the bars that form the chart. We can code all this in a React component, like I did in my <StackedBars /> (see here).

Initially, I created both x and y axes, but I realized the actual axes are unnecessary information in my chart.

Removing what is not important for your audience reduces clutter!

therefore, I let the y-axis as it was, only omitting the path and line elements using CSS style stroke-opacity: 0 (you may try display:none). The x-axis I omitted by removing the React component call.

This is the second important case of React & D3 integration because the d3.axis function needs the SVG element to draw in. It means that we cannot call d3.axis and get an SVG element that we will return in our React component, as we did in the last example.

In this case, we need to give D3 temporary control over the DOM. For that, we select the element that refers to our current component and tell D3 to work on it. Here is an example:

We set our Axis node with ref={(el) => { this.axisElement = el; }} (see above), then we select it with D3 and call the D3 axis function like in here d3.select(this.axisElement).call(axis), which will append the axis elements.

The above example will draw the axis inside the <g> element, and we are returning it all to the parent component after rendered.

ref updates happen before componentDidMount or componentDidUpdate lifecycle methods” — documentation

therefore, first our code executes this.axisElement = el and then renderAxis().

In conclusion, we defined the 2 main approaches to creating SVG visualizations using React and D3:

  1. declaratively: you control the SVG elements;
  2. refs: giving D3 the control over a specific referenced node.

The 1st is preferred and the 2nd should be avoided as much as you can, according to the React documentation. If a function in D3 returns the SVG elements, you can just use the result declaratively (not using ref), if not, ref seems to be the only way to avoid the enter, exit and update functions.

4. Setting up Tooltips

One way to create the tooltips is to build a singular component for each bar or stacked bars; the other, is to build a component that controls all the tooltips.

This is what ReactTooltip does. You only need to set some attributes where your tooltips should appear and the props of one component <ReactTooltip/> that goes outside the SVG. In the element where the tooltip will appear you set 2 props: data-tip and data-for. The first is the text, and the second is the ReactTooltip component id as shown below:

ReactTooltip website: https://www.npmjs.com/package/react-tooltip

5. References to learn D3 & React integration

So far I had contact with content of three main active authors that use D3 and React, create tutorials and share their codes:

6. Behind the scenes

These are some screen shots that I took while coding the chart. As you can see, I started showing the Axes and ended up removing them.

See all these lines and axes? I don’t need them here.
Adjusting the bar sizes and placement.

Please leave your comments or private notes about any of the topics.

Thank you for reading my article!

--

--