Данные не соответствуют домену оси Y

1

Я сгруппировал гистограмму, используя D3. Диаграмма построена с использованием d3.stack() но данные почему-то не совпадают с доменом оси Y, а столбцы имеют очень небольшую высоту. Может кто-нибудь дать мне знать, что мне не хватает?

Snippet:

//DATA
var data = [
  {
    category: "test1",
    type1: 100,
    type2: 200,
    type3: 0,
    column: "column1"
  },
  {
    category: "test1",
    type1: 0,
    type2: 0,
    type3: 500,
    column: "column2"
  },
  {
    category: "test2",
    type1: 150,
    type2: 100,
    type3: 0,
    column: "column1"
  },
  {
    category: "test2",
    type1: 0,
    type2: 0,
    type3: 400,
    column: "column2"
  }
];

//INITIAL SETUP
var margin = { top: 30, right: 10, bottom: 80, left: 80 };
var width = document.documentElement.offsetWidth - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var barwidth = 40;

var graph = d3
  .select("#chart-area")
  .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 + ")");

var x0 = d3
  .scaleBand()
  .rangeRound([0, width])
  .paddingInner(0.1);

var x1 = d3.scaleBand().padding(0.05);

var y = d3.scaleLinear().range([height, 0]).domain([0,500]);

var y1 = d3.scaleBand();

var z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6"]);
var stack = d3.stack().offset(d3.stackOffsetExpand);

x0.domain(
  data.map(function(d) {
    return d.category;
  })
);
x1
  .domain(
    data.map(function(d) {
      return d.column;
    })
  )
  .range([0, x0.bandwidth()])
  .padding(0.2);

z.domain(Object.keys(data[0]).filter(x => x !== "category" && x !== "column"));
var keys = z.domain(); //["type1", "type2", "type3"];

var stackData = stack.keys(keys)(data);

var serie = graph
  .selectAll(".serie")
  .data(stackData)
  .enter()
  .append("g")
  .attr("class", "serie")
  .attr("fill", function(d) {
    return z(d.key);
  });

serie
  .selectAll("rect")
  .data(function(d) {
    return d;
  })
  .enter()
  .append("rect")
  .attr("class", "serie-rect")
  .attr("transform", function(d) {
    return "translate(" + x0(d.data.category) + ",0)";
  })
  .attr("x", function(d) {
    return x1(d.data.column)+x1.bandwidth()/ 2 - 20;
  })
  .attr("y", function(d) {
    return y(d[1]);
  })
  .attr("height", function(d) {
    return y(d[0]) - y(d[1]);
  })
  .attr("width", barwidth);

graph
  .append("g")
  .attr("class", "axis")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x0));

graph
  .append("g")
  .attr("class", "axis")
  .call(d3.axisLeft(y).ticks(null, "s"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart-area"></div>
Теги:
d3.js
svg

1 ответ

1
Лучший ответ

Проблема здесь заключается только в использовании stack.offset(d3.stackOffsetExpand).

Если вы посмотрите на API, вы увидите, что d3.stackOffsetExpand:

Применяет нулевую базовую линию и нормализует значения для каждой точки, так что верхняя линия всегда равна единице.

Поэтому все ваши значения идут от 0 до 1.

Вот тот же код без d3.stackOffsetExpand:

//DATA
var data = [
  {
    category: "test1",
    type1: 100,
    type2: 200,
    type3: 0,
    column: "column1"
  },
  {
    category: "test1",
    type1: 0,
    type2: 0,
    type3: 500,
    column: "column2"
  },
  {
    category: "test2",
    type1: 150,
    type2: 100,
    type3: 0,
    column: "column1"
  },
  {
    category: "test2",
    type1: 0,
    type2: 0,
    type3: 400,
    column: "column2"
  }
];

//INITIAL SETUP
var margin = { top: 30, right: 10, bottom: 80, left: 80 };
var width = document.documentElement.offsetWidth - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var barwidth = 40;

var graph = d3
  .select("#chart-area")
  .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 + ")");

var x0 = d3
  .scaleBand()
  .rangeRound([0, width])
  .paddingInner(0.1);

var x1 = d3.scaleBand().padding(0.05);

var y = d3.scaleLinear().range([height, 0]).domain([0,500]);

var y1 = d3.scaleBand();

var z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6"]);
var stack = d3.stack();

x0.domain(
  data.map(function(d) {
    return d.category;
  })
);
x1
  .domain(
    data.map(function(d) {
      return d.column;
    })
  )
  .range([0, x0.bandwidth()])
  .padding(0.2);

z.domain(Object.keys(data[0]).filter(x => x !== "category" && x !== "column"));
var keys = z.domain(); //["type1", "type2", "type3"];

var stackData = stack.keys(keys)(data);

var serie = graph
  .selectAll(".serie")
  .data(stackData)
  .enter()
  .append("g")
  .attr("class", "serie")
  .attr("fill", function(d) {
    return z(d.key);
  });

serie
  .selectAll("rect")
  .data(function(d) {
    return d;
  })
  .enter()
  .append("rect")
  .attr("class", "serie-rect")
  .attr("transform", function(d) {
    return "translate(" + x0(d.data.category) + ",0)";
  })
  .attr("x", function(d) {
    return x1(d.data.column)+x1.bandwidth()/ 2 - 20;
  })
  .attr("y", function(d) {
    return y(d[1]);
  })
  .attr("height", function(d) {
    return y(d[0]) - y(d[1]);
  })
  .attr("width", barwidth);

graph
  .append("g")
  .attr("class", "axis")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x0));

graph
  .append("g")
  .attr("class", "axis")
  .call(d3.axisLeft(y).ticks(null, "s"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart-area"></div>

С другой стороны, если вы хотите использовать d3.stackOffsetExpand, измените домен y соответствующим образом:

var y = d3.scaleLinear().range([height, 0]);

При удалении домена по умолчанию используется значение [0, 1].

Вот код с этим изменением:

//DATA
var data = [
  {
    category: "test1",
    type1: 100,
    type2: 200,
    type3: 0,
    column: "column1"
  },
  {
    category: "test1",
    type1: 0,
    type2: 0,
    type3: 500,
    column: "column2"
  },
  {
    category: "test2",
    type1: 150,
    type2: 100,
    type3: 0,
    column: "column1"
  },
  {
    category: "test2",
    type1: 0,
    type2: 0,
    type3: 400,
    column: "column2"
  }
];

//INITIAL SETUP
var margin = { top: 30, right: 10, bottom: 80, left: 80 };
var width = document.documentElement.offsetWidth - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var barwidth = 40;

var graph = d3
  .select("#chart-area")
  .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 + ")");

var x0 = d3
  .scaleBand()
  .rangeRound([0, width])
  .paddingInner(0.1);

var x1 = d3.scaleBand().padding(0.05);

var y = d3.scaleLinear().range([height, 0]);

var y1 = d3.scaleBand();

var z = d3.scaleOrdinal().range(["#98abc5", "#8a89a6"]);
var stack = d3.stack().offset(d3.stackOffsetExpand);

x0.domain(
  data.map(function(d) {
    return d.category;
  })
);
x1
  .domain(
    data.map(function(d) {
      return d.column;
    })
  )
  .range([0, x0.bandwidth()])
  .padding(0.2);

z.domain(Object.keys(data[0]).filter(x => x !== "category" && x !== "column"));
var keys = z.domain(); //["type1", "type2", "type3"];

var stackData = stack.keys(keys)(data);

var serie = graph
  .selectAll(".serie")
  .data(stackData)
  .enter()
  .append("g")
  .attr("class", "serie")
  .attr("fill", function(d) {
    return z(d.key);
  });

serie
  .selectAll("rect")
  .data(function(d) {
    return d;
  })
  .enter()
  .append("rect")
  .attr("class", "serie-rect")
  .attr("transform", function(d) {
    return "translate(" + x0(d.data.category) + ",0)";
  })
  .attr("x", function(d) {
    return x1(d.data.column)+x1.bandwidth()/ 2 - 20;
  })
  .attr("y", function(d) {
    return y(d[1]);
  })
  .attr("height", function(d) {
    return y(d[0]) - y(d[1]);
  })
  .attr("width", barwidth);

graph
  .append("g")
  .attr("class", "axis")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(x0));

graph
  .append("g")
  .attr("class", "axis")
  .call(d3.axisLeft(y).ticks(null, "s"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="chart-area"></div>
  • 1
    Слава Богу. Я знал, что была какая-то глупая ошибка. Это то, что произойдет, если я скопирую некоторый код, не зная всех деталей. Спасибо!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню