Я хочу создать чуть более продвинутую гистограмму, которая показывает относительные размеры категорий, а также то, что составляет каждую категорию (подкатегории). Представьте себе диаграмму ниже, но с более чем двумя цветами:
![enter image description here](https://i.stack.imgur.com/cPKuL.png)
До сих пор мне удавалось добиться тривиального прогресса только путем зацикливания массивов, которые я расширены из подкатегории пропорции:
var margins = {top:20, bottom:300, left:30, right:100};
var height = 600;
var width = 900;
var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;
var svg = d3.select('body')
.append('svg')
.attr('width', totalWidth)
.attr('height', totalHeight);
var graphGroup = svg.append('g')
.attr('transform', "translate("+margins.left+","+margins.top+")");
var protoData = [
{'type':'Financial bonds', 'number':1990, 'volume':326.3, 'type1':68.8, 'type2':6.9, 'type3':13.6, 'type4':1.2, 'type5':6, 'type6':1, 'type7':2},
{'type':'Enterprise bonds', 'number':850, 'volume':34.5, 'type1':10, 'type2':20, 'type3':10, 'type4':20, 'type5':40},
{'type':'Corporate bonds', 'number':300, 'volume':34.5, 'type1':10, 'type2':20, 'type3':10, 'type4':20, 'type5':40},
{'type':'Commercial paper', 'number':200, 'volume':34.5, 'type1':10, 'type2':20, 'type3':10, 'type4':20, 'type5':40}
];
var maxRows = 4;
var data = [];
var yScale = d3.scaleLinear()
.domain([0,500])
.range([height,0]);
protoData.forEach(obj => {
data.push(Object.keys(obj).reduce((acc, _, i) =>
acc.concat(d3.range(Math.round(obj["type" + (i + 1)])).map(() => i)), []))
});
//console.log(data)
var colorScale = d3.scaleOrdinal(["#003366","#366092","#4f81b9","#95b3d7","#b8cce4","#e7eef8","#a6a6a6","#d9d9d9"]);
for (var j=0; j<data.length; j++) {
graphGroup.selectAll('rect')
.data(data[j])
.enter()
.append('rect')
.attr('x', function(d, i) {
return ((i / maxRows) % maxRows) * 25 + (j*150)
})
.attr('y', function(d, i) {
return ~~(i/maxRows) * 25;
})
.attr('width', 20)
.attr('height', 20)
.attr('transform', "translate("+0+","+0+")")
.style('fill', function(d) {
return colorScale(d);
});
}
<script src="https://d3js.org/d3.v5.min.js"></script>
Похоже, мои maxRow
logi c отключены ... очень. Этот недостаток помешал мне предпринять дальнейшие шаги. Например, я подозреваю, что в какой-то момент нам нужно ввести лог c для установки maxRows
, равную значению y для этой категории. (yScale
предназначен для использования с d.volume
в данных.)
В настоящее время все массивы имеют длину 100, но в зависимости от значения y может потребоваться изменить размер самого массива. Например, если категория 1 имеет значение y, вдвое большее, чем категория 2, то имеет смысл разделить категорию 1 на 100 квадратов и разделить категорию 2 на 50 квадратов. Это означает, что каждый квадрат в категории 1 стоит 1%, но каждый квадрат в категории 2 будет стоить 2%. И так далее для каждой категории.
Вопрос
Если мы сохраним ширину и высоту каждого квадрата на фрагментированной гистограмме на 20
, то как мы можем построить оставшуюся координату x, y? logi c добавить ректы в соответствии с yScale
и цветовое кодирование colorScale
?
Сложные части, кажется, динамически вычисляют, сколько процентных пунктов стоит один квадрат, потому что в зависимости от высоты категории он будет варьироваться.
Примечание: Я понимаю, что этот форм-фактор отнимает от точности d3.scaleLinear()
, используемой yScale
, поэтому я готов признать, что высоты могут быть не точно пикселей идеальными.