按特定属性的最大值过滤数组的元素

时间:2019-01-16 20:15:05

标签: javascript d3.js

我想对数组的每个元素进行子集化,以便剩下与一个属性的最大值相关联的所有值。我将在D3.js图形中使用此图形,该图形将在数据中每个分组的最大值处具有注释。

例如,这是我如何按物种嵌套虹膜数据集,然后仅获取SepalLength的最大值的方法。

maxdata = d3.nest()
    .key(function (d) { return d.species; })
    .rollup(function (leaves) {
        var maxSepalLength = d3.max(leaves, function (x) { return x.sepalLength })
            return { maxSepalLength:maxSepalLength}
    })
    .entries(irisdata)

输出看起来像这样:

0:
    key: "setosa"
    value:
        maxSepalLength: 5.4
1:
    key: "versicolor"
    value:
        maxSepalLength: 6.8
2:
    key: "virginica"
    value:
        maxSepalLength: 7.9

这通常可以按预期工作,但是我不确定如何保留其他变量。我想要的输出是这样的:

0:
    key: "setosa"
    value:
        maxSepalLength: 5.4
        sepalWidth: <value> 
        petalLength: <value>
        petalWidth: <value>

...etc

摆弄数据的是here。我该如何坚持这些其他价值观?

2 个答案:

答案 0 :(得分:1)

您可以在maxSepalLength数组中查找具有leaves的对象,并将其添加到返回的对象中:

return { maxSepalLength , ...leaves.find(e => e.sepalLength === maxSepalLength) }

编辑:

您可以使用reduce代替d3.max来减少迭代次数:

maxdata = d3.nest()
    .key(function (d) { return d.species; })
    .rollup(function (leaves) {
        return leaves.reduce((max, curr) => {      
        max['maxSepalLength'] = max['maxSepalLength'] || 0;

        if(max['maxSepalLength'] < curr.sepalLength)
            max = {...curr, maxSepalLength : curr.sepalLength};

        return max;
      }, {});      
    })
    .entries(irisdata)

var irisdata = d3.csvParse(d3.select("pre#data").text());
console.log({ irisdata })

irisdata.forEach(function (d) {
    d.sepalLength = +d.sepalLength;
});

maxdata = d3.nest()
    .key(function (d) { return d.species; })
    .rollup(function (leaves) {
    
        var maxSepalLength = d3.max(leaves, function (x) { return x.sepalLength })
     		return { maxSepalLength , ...leaves.find(e => e.sepalLength === maxSepalLength) }
    })
    .entries(irisdata)

console.log({maxdata})
pre {
  display:none;
  }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<pre id="data">
sepalLength,sepalWidth,petalLength,petalWidth,species
5.1,3.5,1.4,0.2,setosa
4.9,3,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5,3.6,1.4,0.2,setosa
5.4,3.9,1.7,0.4,setosa
4.6,3.4,1.4,0.3,setosa
5,3.4,1.5,0.2,setosa
5.3,3.7,1.5,0.2,setosa
5,3.3,1.4,0.2,setosa
6.8,2.8,4.8,1.4,versicolor
6.7,3,5,1.7,versicolor
6,2.9,4.5,1.5,versicolor
5.7,2.6,3.5,1,versicolor
5.5,2.4,3.8,1.1,versicolor
5.5,2.4,3.7,1,versicolor
5.8,2.7,3.9,1.2,versicolor
6,2.7,5.1,1.6,versicolor
5.4,3,4.5,1.5,versicolor
6,3.4,4.5,1.6,versicolor
6.7,3.1,4.7,1.5,versicolor
6.3,2.3,4.4,1.3,versicolor
5.6,3,4.1,1.3,versicolor
5.5,2.5,4,1.3,versicolor
5.5,2.6,4.4,1.2,versicolor
6.1,3,4.6,1.4,versicolor
5.8,2.6,4,1.2,versicolor
5,2.3,3.3,1,versicolor
5.6,2.7,4.2,1.3,versicolor
5.7,3,4.2,1.2,versicolor
5.7,2.9,4.2,1.3,versicolor
6.2,2.9,4.3,1.3,versicolor
5.1,2.5,3,1.1,versicolor
5.7,2.8,4.1,1.3,versicolor
6.3,3.3,6,2.5,virginica
5.8,2.7,5.1,1.9,virginica
7.1,3,5.9,2.1,virginica
5.8,2.8,5.1,2.4,virginica
6.4,3.2,5.3,2.3,virginica
6.5,3,5.5,1.8,virginica
7.7,3.8,6.7,2.2,virginica
7.7,2.6,6.9,2.3,virginica
6,2.2,5,1.5,virginica
6.9,3.2,5.7,2.3,virginica
5.6,2.8,4.9,2,virginica
7.7,2.8,6.7,2,virginica
6.3,2.7,4.9,1.8,virginica
6.7,3.3,5.7,2.1,virginica
7.2,3.2,6,1.8,virginica
6.2,2.8,4.8,1.8,virginica
6.1,3,4.9,1.8,virginica
6.4,2.8,5.6,2.1,virginica
7.2,3,5.8,1.6,virginica
7.4,2.8,6.1,1.9,virginica
7.9,3.8,6.4,2,virginica
6.4,2.8,5.6,2.2,virginica
6.3,2.8,5.1,1.5,virginica
6.1,2.6,5.6,1.4,virginica
7.7,3,6.1,2.3,virginica
6.3,3.4,5.6,2.4,virginica
6.4,3.1,5.5,1.8,virginica
</pre>

答案 1 :(得分:0)

如果我正确理解了您的问题,那么我认为下面的代码可以帮助您解决问题。都是纯JavaScript,没有使用任何d3函数。

基本上,我将您的数据字符串解析为记录数组。我在reduce回调中分析当前记录,以查看该记录是否具有比当前max元素更大的属性值-如果存在,它将变成新的max元素。

我提供了一个名为getMax的函数,该函数将我提到的数据数组作为第一个参数。 getMax使用第二个参数,该参数用于确定要查找最大值的属性。

您可以在下面的演示中看到我通过该函数运行了每个属性名称,并且可以看到数据集如何变化。希望这会有所帮助!

function parse(s) {
  return s.split('\n').filter(el => el.length);
}

function generatePropertyKey(s) {
  var suffix = s.charAt(0).toUpperCase();
  suffix += s.substring(1);
  return `max${suffix}`;
}

function getMax(data, properyName) {
  var o = data.reduce((accum, el, idx) => {
    if (idx > 0) {
      var mk = generatePropertyKey(properyName),
        [
          sepalLength,
          sepalWidth,
          petalLength,
          petalWidth,
          species
        ] = el.split(',')

      var mv;
      switch (properyName) {
        case 'sepalLength':
          mv = sepalLength;
          break;
        case 'sepalWidth':
          mv = sepalWidth;
          break;
        case 'petalLength':
          mv = petalLength;
          break;
        case 'petalWidth':
          mv = petalWidth;
          break;
      }

      if (!accum[species] || (accum[species] && mv > accum[species][mk])) {
        accum[species] = {
          [mk]: mv,
          sepalLength,
          sepalWidth,
          petalLength,
          petalWidth
        };

        delete accum[species][properyName];
      }
    }

    return accum;
  }, {});

  return o;
}


//Demo code:
var data = parse(document.querySelector('#data').innerHTML);

var options = [
  'sepalLength',
  'sepalWidth',
  'petalLength',
  'petalWidth'
];

console.log(options.map(el => getMax(data, el)))
pre {
  display: none;
}
<pre id="data">
sepalLength,sepalWidth,petalLength,petalWidth,species
5.1,3.5,1.4,0.2,setosa
4.9,3,1.4,0.2,setosa
4.7,3.2,1.3,0.2,setosa
4.6,3.1,1.5,0.2,setosa
5,3.6,1.4,0.2,setosa
5.4,3.9,1.7,0.4,setosa
4.6,3.4,1.4,0.3,setosa
5,3.4,1.5,0.2,setosa
5.3,3.7,1.5,0.2,setosa
5,3.3,1.4,0.2,setosa
6.8,2.8,4.8,1.4,versicolor
6.7,3,5,1.7,versicolor
6,2.9,4.5,1.5,versicolor
5.7,2.6,3.5,1,versicolor
5.5,2.4,3.8,1.1,versicolor
5.5,2.4,3.7,1,versicolor
5.8,2.7,3.9,1.2,versicolor
6,2.7,5.1,1.6,versicolor
5.4,3,4.5,1.5,versicolor
6,3.4,4.5,1.6,versicolor
6.7,3.1,4.7,1.5,versicolor
6.3,2.3,4.4,1.3,versicolor
5.6,3,4.1,1.3,versicolor
5.5,2.5,4,1.3,versicolor
5.5,2.6,4.4,1.2,versicolor
6.1,3,4.6,1.4,versicolor
5.8,2.6,4,1.2,versicolor
5,2.3,3.3,1,versicolor
5.6,2.7,4.2,1.3,versicolor
5.7,3,4.2,1.2,versicolor
5.7,2.9,4.2,1.3,versicolor
6.2,2.9,4.3,1.3,versicolor
5.1,2.5,3,1.1,versicolor
5.7,2.8,4.1,1.3,versicolor
6.3,3.3,6,2.5,virginica
5.8,2.7,5.1,1.9,virginica
7.1,3,5.9,2.1,virginica
5.8,2.8,5.1,2.4,virginica
6.4,3.2,5.3,2.3,virginica
6.5,3,5.5,1.8,virginica
7.7,3.8,6.7,2.2,virginica
7.7,2.6,6.9,2.3,virginica
6,2.2,5,1.5,virginica
6.9,3.2,5.7,2.3,virginica
5.6,2.8,4.9,2,virginica
7.7,2.8,6.7,2,virginica
6.3,2.7,4.9,1.8,virginica
6.7,3.3,5.7,2.1,virginica
7.2,3.2,6,1.8,virginica
6.2,2.8,4.8,1.8,virginica
6.1,3,4.9,1.8,virginica
6.4,2.8,5.6,2.1,virginica
7.2,3,5.8,1.6,virginica
7.4,2.8,6.1,1.9,virginica
7.9,3.8,6.4,2,virginica
6.4,2.8,5.6,2.2,virginica
6.3,2.8,5.1,1.5,virginica
6.1,2.6,5.6,1.4,virginica
7.7,3,6.1,2.3,virginica
6.3,3.4,5.6,2.4,virginica
6.4,3.1,5.5,1.8,virginica
</pre>