Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

202
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda