javascript - 将解析的百分比数据转换为新数组

标签 javascript d3.js

假设数据从 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 是否提供了比我的蛮力方法更出色的方法来实现所需的数组?

最佳答案

我想你想创建一个象形图。如果这是正确的,这种 reducemap 的组合可以轻松创建您想要的单个数组,而不管数据对象中的属性数量:

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/

相关文章:

javascript - 为什么这个简单的 AngularJS ng-show 不起作用?

javascript - 如何在没有 if else、switch 或 javascript 中的内置函数的情况下实现逻辑

javascript - 使用 Javascript 更改 HTML 元素的类

javascript - 使用 D3JS 的和弦 DHT 图表

javascript - D3 : After adding a node, 拖动已附加但不起作用

javascript - 我无法在一页上获取多个同型图。我认为问题可能出在 svg <use> 元素 .selectAll ("use")

javascript - 基础轨道 slider 上的全宽图像

javascript - 剧作家无法捕获 response.json()

javascript - 多行 D3.js 折线图中的工具提示样式

d3.js - d3.sparql - 如何直接从 D3js 查询 SPARQL 端点?