Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

206
Views
D3: use an alternate field for axis labels with scaleBand

I'm working on a D3 (V5) chart from a dataset that includes both a JobCode (unique) and JobTitle (not unique). I need to use the JobCode for the axis, but would like to display the JobTitle as the label.

enter image description here

Relevant code:

const xScale = d3.scaleLinear().domain([0,d3.max(grouped, d => d.jobCodeMax)-d3.min(grouped, d => d.jobCodeMax)]).range([0,width-margin.left-margin.right]);
const yScale = d3.scaleBand().domain(grouped.map(d => d.all[0].jobCode)).range([0,height - margin.top - margin.bottom]).padding(0.3);
const yAxis = d3.axisLeft(yScale);
const xAxis = d3.axisTop(xScale);
const radius = yScale.bandwidth()/2.75
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)

yAxis(g.append("g"));
xAxis(g.append("g"));

I can access the jobTitles with d.jobTitle.

My tentative plan is to abandon the d3.axisLeft() function and draw my own. Is there a more straightforward method? Something like a parameter to d3.axisLeft() where I specify an alternate field?

Thank you for any insights.

about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

The domain of d3.scaleBand:

... Domain values are stored internally in an InternMap from primitive value to index; the resulting index is then used to determine the band. Thus, a band scale’s values must be coercible to a primitive value, and the primitive domain value uniquely identifies the corresponding band. ...

InternMap extends a standard Map object which - so we can see that values in the domain of a scaleBand need to be unique.

To get the result you want you can switch the text values to jobTitle after the axis is rendered e.g.:

// replace text values on y axis
yLabels = d3.selectAll(".yaxis g text");
yLabels.each(function(d, i) { d3.select(this).text(data[i].alias) });

Using arrow functions, the equivalent is:

// arrow function way
yLabels = d3.selectAll(".yaxis g text");
yLabels.each((d, i, n) => d3.select(n[i]).text(data[i].alias))

Working example below:

const margin = {top: 10, bottom: 30, left: 60, right: 10}
const width = 500 - margin.left - margin.right;
const height = 180 - margin.top - margin.bottom;
const svg = d3.select("body")
  .append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", `translate(${margin.left}, ${margin.top})`);

const data = [
  {group: "A", value: 3, alias: "foo"}, 
  {group: "B", value: 1, alias: "foo"}, 
  {group: "C", value: 2, alias: "bar"},
  {group: "D", value: 5, alias: "bar"},
  {group: "E", value: 4, alias: "bar"}
];

const xScale = d3.scaleLinear()
  .domain([0, d3.max(data, d => d.value)])
  .range([0, width]);

const yScale = d3.scaleBand()
  .domain(data.map(d => d.group))
  .range([height, 0])
  .padding(.2);

const xAxis = d3.axisBottom(xScale);
const yAxis = d3.axisLeft(yScale);
  
const gXAxis = svg.append("g")
  .attr("transform", `translate(0, ${height})`)
  .call(xAxis);

const gYAxis = svg.append("g")
  .attr("class", "yaxis")
  .call(yAxis);

svg.selectAll(".bar")
  .data(data)
  .enter()
  .append("rect")
  .attr("x", xScale(0))
  .attr("y", d => yScale(d.group))
  .attr("width", d => xScale(d.value))
  .attr("height", yScale.bandwidth())
  .attr("fill", "steelblue");
  
// replace text values on y axis
yLabels = d3.selectAll(".yaxis g text");
yLabels.each(function(d, i) { d3.select(this).text(data[i].alias) });
// arrow function way
//yLabels.each((d, i, n) => d3.select(n[i]).text(data[i].alias))
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!