我试图在直方图中绘制值,但在某些情况下,我无法处理极端值,例如正确绘制了 1,2,25,35,23,60 之类的值,但 1,23 之类的值, 45、60、1000、45000 是如此遥远,以至于 xScale 将域视为 (1, 4500),然后绘制的值非常遥远。有什么办法可以将最后一个元素组合在一起?由于我使用相同的 xScale 域,因此对于此直方图,也以类似的方式生成 bin,如下所述
histogram = d3
.histogram()
.value((d) => d.value)
.domain(xScale.domain())
.thresholds(xScale.ticks(threshold));
bins = histogram(data)
基本上我在这里想的是我需要调整 xScale 的域(如果我是对的)以使垃圾箱正确。我想得到类似 >100 的值,然后结合 1000 和 4500 的最后两个值,然后在考虑上述情况的情况下绘制在同一条上。
答案 0 :(得分:0)
这样的事情怎么样:
<!DOCTYPE html>
<html>
<head>
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<svg></svg>
<script>
// set up normal graph
var margin = {
top: 20,
right: 20,
bottom: 30,
left: 50,
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
// our bin size will be segments of 10
// with a max of 100
// anything over 100 will be binned together
var binSize = 10,
binLimit = 100;
// some fake data, 100 points < 100
// 10 points possibly > 100
var data = d3
.range(100)
.map(() => {
return { value: Math.random() * binLimit };
})
.concat(
d3.range(10).map(() => {
return { value: Math.random() * 5000 };
})
);
// max value in data set
var maxValue = d3.max(data, (d) => {
return d.value;
});
// set the parameters for the histogram
var histogram = d3
.histogram()
.value((d) => {
return d.value;
})
.domain([0, maxValue])
// thresholds would be [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
// so anything >100 will be binned at end
.thresholds(d3.range(0,110,10));
var bins = histogram(data);
var x = d3.scaleLinear()
.range([0, width])
// set our scale to have a domain with two extra increments at the end
.domain([0, binLimit + (binSize * 2)]);
// set up svg object
var svg = d3
.select('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g')
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
// add x-axis
svg
.append('g')
.attr('transform', 'translate(0,' + height + ')')
.attr('class', 'x-axis')
.call(d3.axisBottom(x));
// y-axis
var y = d3.scaleLinear().range([height, 0]);
y.domain([
0,
d3.max(bins, function (d) {
return d.length;
}),
]);
svg.append('g').call(d3.axisLeft(y));
var bWidth = x(bins[0].x1) - x(bins[0].x0) - 1
// append our rects
svg
.selectAll('rect')
.data(bins)
.enter()
.append('rect')
.attr('x', 1)
.attr('transform', function (d) {
if (d.x1 > 100){
// if this is the last bin
// place it in our special column on the end
return 'translate(' + x(binLimit + binSize) + ',' + y(d.length) + ')';
} else {
return 'translate(' + x(d.x0) + ',' + y(d.length) + ')';
}
})
.attr('width', bWidth)
.attr('height', function (d) {
return height - y(d.length);
})
.style('fill', '#69b3a2');
// modify last two labels
document.querySelector('.x-axis .tick:nth-last-child(2)')
.children[1].innerHTML = '>100';
document.querySelector('.x-axis .tick:nth-last-child(1)')
.children[1].innerHTML = '<5000';
</script>
</body>
</html>