Horizontal Bar-IV
The best form of practice is imitation.So today I will try to immitate a graph that I saw on r/dataisbeautiful .It is similar to the previous template. We do need to curate the data to match the data that we feed to our bar chart component. The data set for this graph can be found at olympics data set . So let's get started.
The first objective of visualization is to curate the data. So let's look at the data set.
"ID","Name","Sex","Age","Height","Weight","Team","NOC","Games","Year","Season","City","Sport","Event","Medal"
"1","A Dijiang","M",24,180,80,"China","CHN","1992 Summer",1992,"Summer","Barcelona","Basketball","Basketball Men's Basketball",NA
"2","A Lamusi","M",23,170,60,"China","CHN","2012 Summer",2012,"Summer","London","Judo","Judo Men's Extra-Lightweight",NA
"3","Gunnar Nielsen Aaby","M",24,NA,NA,"Denmark","DEN","1920 Summer",1920,"Summer","Antwerpen","Football","Football Men's Football",NA
"4","Edgar Lindenau Aabye","M",34,NA,NA,"Denmark/Sweden","DEN","1900 Summer",1900,"Summer","Paris","Tug-Of-War","Tug-Of-War Men's Tug-Of-War","Gold"
"5","Christine Jacoba Aaftink","F",21,185,82,"Netherlands","NED","1988 Winter",1988,"Winter","Calgary","Speed Skating","Speed Skating Women's 500 metres",NA
"5","Christine Jacoba Aaftink","F",21,185,82,"Netherlands","NED","1988 Winter",1988,"Winter","Calgary","Speed Skating","Speed Skating Women's 1,000 metres",NA
"5","Christine Jacoba Aaftink","F",25,185,82,"Netherlands","NED","1992 Winter",1992,"Winter","Albertville","Speed Skating","Speed Skating Women's 500 metres",NA
"5","Christine Jacoba Aaftink","F",25,185,82,"Netherlands","NED","1992 Winter",1992,"Winter","Albertville","Speed Skating","Speed Skating Women's 1,000 metres",NA
"5","Christine Jacoba Aaftink","F",27,185,82,"Netherlands","NED","1994 Winter",1994,"Winter","Lillehammer","Speed Skating","Speed Skating Women's 500 metres",NA
"5","Christine Jacoba Aaftink","F",27,185,82,"Netherlands","NED","1994 Winter",1994,"Winter","Lillehammer","Speed Skating","Speed Skating Women's 1,000 metres",NA
"6","Per Knut Aaland","M",31,188,75,"United States","USA","1992 Winter",1992,"Winter","Albertville","Cross Country Skiing","Cross Country Skiing Men's 10 kilometres",NAIt is in csv format and has lot of data points. The above list is just a few lines from the data set file. As per the graph created in the post we will need year,male,femal participations. It will be much more better if the data is preprocessed with some better tools like excel,pandas-python,R than feed into d3 but we will try it purely with d3.
d3.csv(location)
.then(
process and return
)So for data curation. I grouped the data by year, sorted in ascending order by year than calucated the total number of male and female athletes. I used d3 group,sum and ascending function for the processing. I read the data from a file then I grouped them with d3.group, sorted the result with d3.ascending. Lastly, created an array with 4 columns with the help of d3.sum .
csv(location).then(value => {
const newValue = Array.from(group(value, d => d.Year))
.sort((a, b) => ascending(a[0], b[0]))
.map(a => ({
Year: a[0],
Female: sum(a[1], d => d.Sex === 'F'),
Male: sum(a[1], d => d.Sex === 'M'),
Total: a[1].length
}))
setDatas(newValue)
})
So the new data looks like
{Year: "1896", Female: 0, Male: 380, Total: 380}
{Year: "1900", Female: 33, Male: 1903, Total: 1936}
{Year: "1904", Female: 16, Male: 1285, Total: 1301}
{Year: "1906", Female: 11, Male: 1722, Total: 1733}
{Year: "1908", Female: 47, Male: 3054, Total: 3101}
{Year: "1912", Female: 87, Male: 3953, Total: 4040}
{Year: "1920", Female: 134, Male: 4158, Total: 4292}Let's start carving the pie
After the first projection above where I projected the total. I realized the reddit plot was doing 100% of total athlete every olympic year and then divinding it into male and female. I guess got carried away on copying stuff without making sense. So back to the data curation step. Now I need to show male and female over hundered percentage. First let see the male Percentage
Now looking at the female Athletes
Finally lets copy the example
Basically the only trick on this graph was making two rectangle one over the other and just translating one at the end of the other one. So I created two rectangle respectively
<rect
fill={maleColor}
x={margin.left}
y={yScale(a.Year)}
width={xScale(a.Male)}
height={yScale.bandwidth()} />
<rect
fill={femaleColor}
x={margin.left}
y={yScale(a.Year)}
width={xScale(a.Female)}
height={yScale.bandwidth()} />Made a male rectangle at the back and female at the front. So now only thing left is to move the female bar chart up to the end of the male chart by using translate in the group svg component.
datas.map((a, index) => (
<g>
<rect
fill={maleColor}
x={margin.left}
y={yScale(a.Year)}
width={xScale(a.Male)}
height={yScale.bandwidth()} />
<g transform={`translate(${xScale(a.Male),0)}`}>
<rect
fill={femaleColor}
x={margin.left}
y={yScale(a.Year)}
width={xScale(a.Female)}
height={yScale.bandwidth()} />
</g>
</g>
))I had to add some back slash on transform as the code was not translating to html on my end properly so remove all the back slash from it. Don't forget to add keys to the components or else react will complain about it.