假设数据从 tsv 中解析如下:
tsvData.then(function(rawData) {
var data = rawData.map(function(d) {
return {year:+d.year, age3:+d.age3*100, age1:+d.age1*100, age2:+d.age2*100, age4:+d.age4*100, age5:+d.age5*100, age6:+d.age6*100, age7:+d.age7*100}
});
并假设我们打算创建一个表示这些百分比的方阵(1 个矩形 = 1%,每个年龄组 = 不同的颜色):
var maxColumn = 10;
var colorMap = {
0:"#003366",
1:"#366092",
2:"#4f81b9",
3:"#95b3d7",
4:"#b8cce4",
5:"#e7eef8",
6:"#f6d18b"
};
graphGroup.selectAll('rect')
.data(data1)
.enter()
.append('rect')
.attr('x', function(d, i) {
return (i % maxColumn) * 30
})
.attr('y', function(d, i) {
return ~~((i / maxColumn) % maxColumn) * 30
})
.attr('width', 20)
.attr('height', 20)
.style('fill', function(d) {
return colorMap[d];
});
我们需要一些方法来转换 data
以使其具有 100 个项目,而这 100 个项目需要与 data
的比例相匹配。为简单起见,我们只在 data[0]
处求值。这是我的解决方案:
var data1 = d3.range(100).map(function(d,i) {
var age1 = data[0].age1;
var age2 = data[0].age2;
var age3 = data[0].age3;
var age4 = data[0].age4;
var age5 = data[0].age5;
var age6 = data[0].age6;
var age7 = data[0].age7;
if (i<age1) {
return 0;
} else if (i>age1 && i<(age1+age2)) {
return 1;
} else if (i>(age1+age2) && i<(age1+age2+age3)) {
return 2;
} else if (i>(age1+age2+age3) && i<(age1+age2+age3+age4)) {
return 3;
} else if (i>(age1+age2+age3+age4) && i<(age1+age2+age3+age4+age5)) {
return 4;
} else if (i>(age1+age2+age3+age4+age5) && i<(age1+age2+age3+age4+age5+age6)) {
return 5;
} else if (i>(age1+age2+age3+age4+age5+age6) && i<(age1+age2+age3+age4+age5+age6+age7)) {
return 6;
}
});
它种类 的作品,但它根本不可扩展,但我无法想象还有什么其他方式可以转换数组。我们很清楚,通过转换数组,我的意思是我们从:
data = [
{'age1':33.66, 'age2':14.87, 'age3':18, 'age4':14, 'age5':11, 'age6':5, 'age7':3}
];
结束于:
data1 = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1...];
var margins = {top:100, bottom:300, left:100, 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 tsvData = d3.tsv('so-demo3.tsv');
var maxColumn = 10;
//tsvData.then(function(rawData) {
/*
var data = rawData.map(function(d) {
return {year:+d.year, age3:+d.age3*100, age1:+d.age1*100, age2:+d.age2*100, age4:+d.age4*100, age5:+d.age5*100, age6:+d.age6*100, age7:+d.age7*100}
});
*/
var data = [
{'age1':33.66, 'age2':14.87, 'age3':18, 'age4':14, 'age5':11, 'age6':5, 'age7':3}
];
var data1 = d3.range(100).map(function(d,i) {
var age1 = data[0].age1;
var age2 = data[0].age2;
var age3 = data[0].age3;
var age4 = data[0].age4;
var age5 = data[0].age5;
var age6 = data[0].age6;
var age7 = data[0].age7;
if (i<age1) {
return 0;
} else if (i>age1 && i<(age1+age2)) {
return 1;
} else if (i>(age1+age2) && i<(age1+age2+age3)) {
return 2;
} else if (i>(age1+age2+age3) && i<(age1+age2+age3+age4)) {
return 3;
} else if (i>(age1+age2+age3+age4) && i<(age1+age2+age3+age4+age5)) {
return 4;
} else if (i>(age1+age2+age3+age4+age5) && i<(age1+age2+age3+age4+age5+age6)) {
return 5;
} else if (i>(age1+age2+age3+age4+age5+age6) && i<(age1+age2+age3+age4+age5+age6+age7)) {
return 6;
}
});
var colorMap = {
0:"#003366",
1:"#366092",
2:"#4f81b9",
3:"#95b3d7",
4:"#b8cce4",
5:"#e7eef8",
6:"#f6d18b"
};
graphGroup.selectAll('rect')
.data(data1)
.enter()
.append('rect')
.attr('x', function(d, i) {
return (i % maxColumn) * 30
})
.attr('y', function(d, i) {
return ~~((i / maxColumn) % maxColumn) * 30
})
.attr('width', 20)
.attr('height', 20)
.style('fill', function(d) {
return colorMap[d];
});
//})
<script src="https://d3js.org/d3.v5.min.js"></script>
问题
d3 是否提供了比我的蛮力方法更出色的方法来实现所需的数组?
最佳答案
我想你想创建一个象形图。如果这是正确的,这种 reduce
和 map
的组合可以轻松创建您想要的单个数组,而不管数据对象中的属性数量:
data.forEach(obj => {
modifiedData.push(Object.keys(obj).reduce((acc, _, i) =>
acc.concat(d3.range(Math.round(obj["age" + (i + 1)])).map(() => i)), []))
});
请注意,由于您无法保证对象中属性的顺序,因此 reduce
使用 "age"+ index
的括号表示法来正确设置数字 0、1、2 等。
到 age1、age2、age3 等。
。
这是演示:
const data = [{
'age1': 33.66,
'age2': 14.87,
'age3': 18,
'age4': 14,
'age5': 11,
'age6': 5,
'age7': 3
}];
const modifiedData = [];
data.forEach(obj => {
modifiedData.push(Object.keys(obj).reduce((acc, _, i) =>
acc.concat(d3.range(Math.round(obj["age" + (i + 1)])).map(() => i)), []))
});
console.log(modifiedData)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
顺便说一下,您当前的数据样本总和不是 100。
关于javascript - 将解析的百分比数据转换为新数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57687815/