В вашем коде есть несколько проблем, основной из которых является массив 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());
Несколько заключительных соображений: мне не ясно, почему вы смешиваете var
и const
. Кроме того, избегайте пробелов в 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>