条形图:在 D3 v5 中排序时如何将数据与国家/地区对齐?
Bar chart: how could I align the data with countries when sorting in D3 v5?
我现在正尝试在条形图中对国家/地区的数据进行排序,但是当我按升序对数据进行排序时,数据和国家/地区之间没有对齐。
这是我编写的代码(我必须删除文件的某些部分,因为我的代码很长):
"use strict";
var third_width = 1000;
var third_height = 500;
var third_padding = 30;
var third_countries = ["Australia", "Austria", "Denmark", "Netherlands","New Zealand", "Norway", "Sweden", "UK","USA","Japan","Poland","Finland","Italy","France","Belgium"]
var third_data = [102, 39, 81, 50, 61, 79, 81, 77, 59, 64, 56, 65, 57, 85, 50];
// The value should be: Australia: 102; Austria: 39; and so on.
// Creating map between two arrays.
const buildMap = (third_countries, third_data) => {
const map = new Map();
for(let i = 0; i < third_countries.length; i++){
map.set(third_countries[i], third_data[i]);
};
return map;
};
var numValues = third_data.length;
var sortAscending = function() {
third_svg.selectAll("rect")
.sort(function(a, b) {
return d3.ascending(a, b);
})
.attr("x", function(d, i) {
return third_xScale(i);
});
}
var sortDescending = function() {
third_svg.selectAll("rect")
.sort(function(a, b) {
return d3.descending(a, b);
})
.attr("x", function(d, i) {
return third_xScale(i);
})
.transition()
.delay(function(d,i){
return i /numValues * 1000;
})
.duration(2000)
.ease(d3.easeElasticOut);
}
d3.select("#sortascending").on("click", function() {
sortAscending();
})
d3.select("#sortdescending").on("click", function() {
sortDescending();
})
这是结果(如您所见,我排序前后的 x 轴相同)。
你们能帮我知道如何对齐 x 轴数据,以便国家在排序后与正确的数据对齐吗?
谢谢!
您需要按值对国家/地区进行排序,然后按相同顺序对它们的名称进行排序:
const sortCountries = (countries, values) => {
let inputCountries = [...countries];
let inputValues = [...values];
const sortedValues = [...values].sort((a, b) => a - b);
const sortedCountries = sortedValues.map(val => {
const index = inputValues.findIndex(v => v === val);
const country = inputCountries[index];
inputValues = [...inputValues.slice(0, index), ...inputValues.slice(index + 1)]
inputCountries = [...inputCountries.slice(0, index), ...inputCountries.slice(index + 1)]
return country;
});
return {sortedCountries, sortedValues};
}
const {sortedCountries, sortedValues} = sortCountries(third_countries, third_data);
现在,将代码中的 third_data
替换为 sortedValues
,将 third_countries
替换为 sortedCountries
。查看代码段中的结果(基于您之前的问题):
const sortCountries = (countries, values) => {
let inputCountries = [...countries];
let inputValues = [...values];
const sortedValues = [...values].sort((a, b) => a - b);
const sortedCountries = sortedValues.map(val => {
const index = inputValues.findIndex(v => v === val);
const country = inputCountries[index];
inputValues = [...inputValues.slice(0, index), ...inputValues.slice(index + 1)]
inputCountries = [...inputCountries.slice(0, index), ...inputCountries.slice(index + 1)]
return country;
});
return {sortedCountries, sortedValues};
}
const third_width = 1000;
const third_height = 450;
const third_padding = 30;
const third_countries = ["Australia", "Austria", "Denmark", "Netherlands","New Zealand", "Norway", "Sweden", "UK","USA","Japan","Poland","Finland","Italy","France","Belgium"]
const third_data = [102, 39, 81, 50, 61, 79, 81, 77, 59, 64, 56, 65, 57, 85, 50];
const {sortedCountries, sortedValues} = sortCountries(third_countries, third_data);
const third_xScale = d3.scaleBand()
.domain(d3.range(sortedValues.length))
.rangeRound([third_padding ,third_width])
.paddingInner(0.1);
const third_yScale = d3.scaleLinear()
.domain([0, d3.max(sortedValues)])
.range([third_height - third_padding, third_padding]);
const third_xAxis = d3.axisBottom()
.scale(third_xScale).tickFormat(function(i) {return sortedCountries[i];})
const third_yAxis = d3.axisLeft()
.scale(third_yScale).ticks(5);
const third_svg = d3.select("#chart3")
.append("svg")
.attr("width", third_width)
.attr("height", third_height);
third_svg.selectAll("rect")
.data(sortedValues)
.enter()
.append("rect")
.attr("x", (d, i) => third_xScale(i))
.attr('y', d => third_yScale(d))
.attr("height", d => third_height - third_padding - third_yScale(d))
.attr("width", third_xScale.bandwidth())
.attr("fill", d => `rgb(0, 0, ${d * 2})`);
//Create "Food waste per capita (kg/year)" on Y Axis
third_svg.append('text')
.attr('x', 5)
.attr('y', 20)
.attr('text-anchor', 'left')
.style('font-family', 'Helvetica')
.style('font-size', 'small')
.text('Food waste per capita (kg/year)');
third_svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + third_padding + ",0)")
.call(third_yAxis);
third_svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0,"+ (third_height - third_padding) + ")")
.call(third_xAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<div id="chart3" />
我现在正尝试在条形图中对国家/地区的数据进行排序,但是当我按升序对数据进行排序时,数据和国家/地区之间没有对齐。 这是我编写的代码(我必须删除文件的某些部分,因为我的代码很长):
"use strict";
var third_width = 1000;
var third_height = 500;
var third_padding = 30;
var third_countries = ["Australia", "Austria", "Denmark", "Netherlands","New Zealand", "Norway", "Sweden", "UK","USA","Japan","Poland","Finland","Italy","France","Belgium"]
var third_data = [102, 39, 81, 50, 61, 79, 81, 77, 59, 64, 56, 65, 57, 85, 50];
// The value should be: Australia: 102; Austria: 39; and so on.
// Creating map between two arrays.
const buildMap = (third_countries, third_data) => {
const map = new Map();
for(let i = 0; i < third_countries.length; i++){
map.set(third_countries[i], third_data[i]);
};
return map;
};
var numValues = third_data.length;
var sortAscending = function() {
third_svg.selectAll("rect")
.sort(function(a, b) {
return d3.ascending(a, b);
})
.attr("x", function(d, i) {
return third_xScale(i);
});
}
var sortDescending = function() {
third_svg.selectAll("rect")
.sort(function(a, b) {
return d3.descending(a, b);
})
.attr("x", function(d, i) {
return third_xScale(i);
})
.transition()
.delay(function(d,i){
return i /numValues * 1000;
})
.duration(2000)
.ease(d3.easeElasticOut);
}
d3.select("#sortascending").on("click", function() {
sortAscending();
})
d3.select("#sortdescending").on("click", function() {
sortDescending();
})
这是结果(如您所见,我排序前后的 x 轴相同)。
谢谢!
您需要按值对国家/地区进行排序,然后按相同顺序对它们的名称进行排序:
const sortCountries = (countries, values) => {
let inputCountries = [...countries];
let inputValues = [...values];
const sortedValues = [...values].sort((a, b) => a - b);
const sortedCountries = sortedValues.map(val => {
const index = inputValues.findIndex(v => v === val);
const country = inputCountries[index];
inputValues = [...inputValues.slice(0, index), ...inputValues.slice(index + 1)]
inputCountries = [...inputCountries.slice(0, index), ...inputCountries.slice(index + 1)]
return country;
});
return {sortedCountries, sortedValues};
}
const {sortedCountries, sortedValues} = sortCountries(third_countries, third_data);
现在,将代码中的 third_data
替换为 sortedValues
,将 third_countries
替换为 sortedCountries
。查看代码段中的结果(基于您之前的问题):
const sortCountries = (countries, values) => {
let inputCountries = [...countries];
let inputValues = [...values];
const sortedValues = [...values].sort((a, b) => a - b);
const sortedCountries = sortedValues.map(val => {
const index = inputValues.findIndex(v => v === val);
const country = inputCountries[index];
inputValues = [...inputValues.slice(0, index), ...inputValues.slice(index + 1)]
inputCountries = [...inputCountries.slice(0, index), ...inputCountries.slice(index + 1)]
return country;
});
return {sortedCountries, sortedValues};
}
const third_width = 1000;
const third_height = 450;
const third_padding = 30;
const third_countries = ["Australia", "Austria", "Denmark", "Netherlands","New Zealand", "Norway", "Sweden", "UK","USA","Japan","Poland","Finland","Italy","France","Belgium"]
const third_data = [102, 39, 81, 50, 61, 79, 81, 77, 59, 64, 56, 65, 57, 85, 50];
const {sortedCountries, sortedValues} = sortCountries(third_countries, third_data);
const third_xScale = d3.scaleBand()
.domain(d3.range(sortedValues.length))
.rangeRound([third_padding ,third_width])
.paddingInner(0.1);
const third_yScale = d3.scaleLinear()
.domain([0, d3.max(sortedValues)])
.range([third_height - third_padding, third_padding]);
const third_xAxis = d3.axisBottom()
.scale(third_xScale).tickFormat(function(i) {return sortedCountries[i];})
const third_yAxis = d3.axisLeft()
.scale(third_yScale).ticks(5);
const third_svg = d3.select("#chart3")
.append("svg")
.attr("width", third_width)
.attr("height", third_height);
third_svg.selectAll("rect")
.data(sortedValues)
.enter()
.append("rect")
.attr("x", (d, i) => third_xScale(i))
.attr('y', d => third_yScale(d))
.attr("height", d => third_height - third_padding - third_yScale(d))
.attr("width", third_xScale.bandwidth())
.attr("fill", d => `rgb(0, 0, ${d * 2})`);
//Create "Food waste per capita (kg/year)" on Y Axis
third_svg.append('text')
.attr('x', 5)
.attr('y', 20)
.attr('text-anchor', 'left')
.style('font-family', 'Helvetica')
.style('font-size', 'small')
.text('Food waste per capita (kg/year)');
third_svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + third_padding + ",0)")
.call(third_yAxis);
third_svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0,"+ (third_height - third_padding) + ")")
.call(third_xAxis);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.7.0/d3.min.js"></script>
<div id="chart3" />