Reputation: 401
I would like to make a bar chart, where every bar represents the frequency of a certain word.
My data is an array of objects, with each having the property word
and freq
.
I declared my axis like that :
let echelleX = d3.scaleBand()
.domain(d3.extent(data, d => d.word))
.range([marges.left, width - marges.right])
.padding(0.1);
And called it :
svg.append("g")
.attr("class","axeX")
.attr("transform", `translate(0,${height})`)
.call(axeX)
.selectAll("text")
.attr("font-weight", "normal")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".5em")
.attr("transform", "rotate(-65)");
I then add my bars to the svg :
svg.append("g").selectAll(".barre").data(data).enter()
.append("rect")
.attr("class", "barre")
.attr("x", (d,i) => echelleX(d.word))
.attr("y", (d) => echelleY(d.freq))
.attr("width", 2.5)
.attr("height", d => height - echelleY(d.freq))
.attr("fill","steelblue");
But the result is this :
When I change this line
.attr("x", (d,i) => echelleX(d.word))
To
.attr("x", (d,i) => marges.left + i*3)
I get this, which is better, but the labels of the axis still don't match.
I checked the documentation of d3.scaleBand and tried a few tweaks but I can't seem to make it work the way I would want to. What am I missing? I would like every bar (d.freq
) to have its corresponding label (d.word
) underneath it on the axis.
Upvotes: 0
Views: 769
Reputation: 15982
Band scales are ordinal instead of linear, which means you need to provide every possible value to the domain instead of just the min/max. D3 cannot interpolate ordinal values.
Try this
.domain(data.map(d => d.word))
You will also have to revert the change you made to the x
attr, the band scale should take care of that.
EDIT: Made the mistake of thinking d3.map
did the same thing as array map.
Upvotes: 1