Make A Group Bar Chart After Nesting Data In D3 Using CSV
I am not really familiar with D3 and I am struggling with the concept of creating a group bar chart after I nested the specific data. The grouped bar chart I am trying to create es
Solution 1:
Consider the following. Your start was good, but you need to have two x-axes. One divides the total domain up into equal spots per residence, and one that takes that residence area and divides it per year.
You can easily use x.bandwidth()
to get the size of that area.
const dataString = `Name, Residence, ID, Schoolyear, Major
Bill Thornton, Davis Hall, 11123, Sophomore, Mathematics
Savannah Lipscombe, Jameson Hall, 11231, Freshman, Biology
Jay Price, Davis Hall, 12222, Senior, Business
Hassan Abdullah, Arthur Hall, 11111, Junior, Mechanical Engineering
John Doe, Arthur Hall, 11112, Junior, Mechanical Engineering
Jo Park, Reed Hall, 22123, Freshman, Political Science`.replace(/, /g, ",");
const unique = array => array.filter((v, i) => array.indexOf(v) === i);
const data = d3.csvParse(dataString);
const years = unique(data.map(d => d.Schoolyear));
var groupedData = d3.nest()
.key(d => d.Residence)
.key(d => d.Schoolyear)
.rollup(v => v.length)
.entries(data)
console.log(groupedData);
const svg = d3.select("svg"),
margin = {
top: 35,
left: 35,
bottom: 0,
right: 0
},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
const x = d3.scaleBand()
.range([margin.left, width - margin.right])
// The residences
.domain(groupedData.map(d => d.key))
.padding(0.1);
const subX = d3.scaleBand()
.range([0, x.bandwidth()])
.domain(years)
.padding(0.05);
// Calculate the nested max
const max = d3.max(
groupedData,
d => d3.max(d.values, e => e.value)
);
const y = d3.scaleLinear()
.domain([0, max])
.range([height - margin.bottom, margin.top]);
const z = d3.scaleOrdinal()
.range(["steelblue", "darkorange", "lightblue"])
.domain(years);
const xAxis = svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.attr("class", "x-axis")
const yAxis = svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.attr("class", "y-axis")
svg.selectAll(".y-axis")
.call(d3.axisLeft(y)
.ticks(null, "s"))
const bargroups = svg.selectAll("g.bargroup")
.data(groupedData, d => d.key)
bargroups.exit().remove()
const bars = bargroups.enter()
.append("g")
.classed("bargroup", true)
.merge(bargroups)
.attr("transform", d => `translate(${x(d.key)}, 0)`)
.selectAll("rect")
.data(d => d.values, e => e.key);
bars.exit().remove()
bars.enter()
.append("rect")
.attr("width", subX.bandwidth())
.merge(bars)
.attr("x", d => subX(d.key))
.attr("y", d => y(d.value))
.attr("height", d => height - y(d.value))
.attr("fill", d => z(d.key))
// Draw the main axis labels
xAxis
.call(d3.axisBottom(x)
.tickSize(0)
.tickPadding(24));
// For every tick, add the year labels
xAxis.selectAll(".tick")
.each(function() {
d3.select(this)
.selectAll(".year-tick")
.data(years)
.enter()
.append("text")
.classed("year-tick", true)
.attr("fill", "currentColor")
.attr("text-anchor", "middle")
.attr("y", (d, i) => i % 2 === 0 ? 3 : 12)
.attr("dy", "0.71em")
.attr("x", d => subX(d) - (x.bandwidth() / 2))
.attr("dx", d => subX.bandwidth() / 2)
.text(d => d);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="700" height="300"></svg>
Post a Comment for "Make A Group Bar Chart After Nesting Data In D3 Using CSV"