错误:<rect>属性和预期长度d3.js

时间:2019-11-10 08:11:26

标签: javascript d3.js bar-chart

我是d3.js的新手,并且我有一个示例CSV文件

import { 
  select,
  csv,
  scaleLinear,
  max,
  scaleBand,
  axisLeft,
    axisBottom} 
from 'd3';

const svg = select('svg');

const width = +svg.attr('width');
const height = +svg.attr('height');

const render = data =>{
  const margin = { top: 20, right: 40, bottom: 20, left: 100 };
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;

  const ChinaFilter = data.filter(function(d){ 
    return d.country.match ('China');
  });
  const IndonesiaFilter = data.filter(function(d){ 
    return d.country.match ('Indonesia');
  });
  const RussiaFilter = data.filter(function(d){ 
    return d.country.match ('Russia');
  });
  var Filter = [ChinaFilter.length,IndonesiaFilter.length,RussiaFilter.length];
  var countryFilter = ['China','Indonesia','Russia'];


  const xScale = scaleLinear()
    .domain([0, max(Filter)])
    .range([0, innerWidth]);


  const yScale = scaleBand()
    .domain(countryFilter)
    .range([0, innerHeight])
        .padding(0.1);


const g = svg.append('g')
    .attr('transform', `translate(${margin.left},${margin.top})`);

  g.append('g').call(axisLeft(yScale));
  g.append('g').call(axisBottom(xScale))
    .attr('transform', `translate(0,${innerHeight})`);

    g.selectAll('rect').data(data)
    .enter().append('rect')
    .attr('y', yScale(countryFilter))
    .attr('width', xScale(Filter))
    .attr('height', yScale.bandwidth());


};

csv('data.csv').then(data => {
    render(data);
});

完成并显示x轴和y轴后,无法创建和显示对应的条并显示该条。这是完整的代码

{{1}}

实际结果[1]:https://i.stack.imgur.com/rFJNU.png

以条形图格式显示的预期产出应为(China,3)(Indonesia,3)(Russia,4)

1 个答案:

答案 0 :(得分:0)

您的代码中有几个问题,主要是data数组。如果这是您的CSV:

country, year
China 1,1998-12-1
China 2,1999-12-1
China 3,2000-12-1
Indonesia 1,1999-12-1
Indonesia 2,1999-12-1
Indonesia 3,1998-12-1
Russia 1,1999-12-1
Russia 2,1998-12-1
Russia 3,1999-12-1
Russia 4,1998-12-1

这意味着您的data是一个包含10个对象的数组,因此我们希望在条形图中看到10条。事实并非如此。由于您只想显示每个国家的记录数,所以我们创建一个正确的数据数组,这里命名为correctData

var countryFilter = ['China', 'Indonesia', 'Russia'];
var correctData = countryFilter.map(function(d) {
    return {
      country: d,
      length: data.filter(function(e) {
        return e.country.match(d);
      }).length
    }
});

然后,我们更改比例:

const xScale = d3.scaleLinear()
    .domain([0, d3.max(correctData, function(d) {
      return d.length
    })])
    .range([0, innerWidth]);

const yScale = d3.scaleBand()
    .domain(correctData.map(function(d) {
      return d.country
    }))
    .range([0, innerHeight])
    .padding(0.1);

最后,使用基准创建条形:

g.selectAll('rect').data(correctData)
    .enter().append('rect')
    .attr('y', function(d) {
      return yScale(d.country)
    })
    .attr('width', function(d) {
      return xScale(d.length)
    })
    .attr('height', yScale.bandwidth());

一些最终的考虑因素:我不清楚您为什么混用varconst。另外,请避免在CSV中留空格。

这是您所做的更改的代码:

const csv = `country, year
China 1,1998-12-1
China 2,1999-12-1
China 3,2000-12-1
Indonesia 1,1999-12-1
Indonesia 2,1999-12-1
Indonesia 3,1998-12-1
Russia 1,1999-12-1
Russia 2,1998-12-1
Russia 3,1999-12-1
Russia 4,1998-12-1`;

const data = d3.csvParse(csv);

const svg = d3.select('svg');

const width = +svg.attr('width');
const height = +svg.attr('height');

const render = data => {
  const margin = {
    top: 20,
    right: 40,
    bottom: 20,
    left: 100
  };
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;

  var countryFilter = ['China', 'Indonesia', 'Russia'];
  var correctData = countryFilter.map(function(d) {
    return {
      country: d,
      length: data.filter(function(e) {
        return e.country.match(d);
      }).length
    }
  });

  const xScale = d3.scaleLinear()
    .domain([0, d3.max(correctData, function(d) {
      return d.length
    })])
    .range([0, innerWidth]);

  const yScale = d3.scaleBand()
    .domain(correctData.map(function(d) {
      return d.country
    }))
    .range([0, innerHeight])
    .padding(0.1);

  const g = svg.append('g')
    .attr('transform', `translate(${margin.left},${margin.top})`);

  g.append('g').call(d3.axisLeft(yScale));
  g.append('g').call(d3.axisBottom(xScale))
    .attr('transform', `translate(0,${innerHeight})`);

  g.selectAll('rect').data(correctData)
    .enter().append('rect')
    .attr('y', function(d) {
      return yScale(d.country)
    })
    .attr('width', function(d) {
      return xScale(d.length)
    })
    .attr('height', yScale.bandwidth());
};

render(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg width="500" height="200"></svg>