D3 nesting and object traversal

2019-09-14 17:16发布

i have a json as shared below and I am trying to nest the data prior to visualization. I wish to plot under gov and non-gov how every vendor is distributed for high and low projects so trying to create a json object like [{v1: {Gov: {high:3, low:2}, {Non-Gov: {high:12, low:1}}}, {v2:{Gov: {high:3, low:2}, {Non-Gov: {high:12, low:1}}}, ...]

I am able to nest the data but unable to get the respective counts. Any guidance is appreciated. Apologies if the question construct is vague.

    [
  {
    "vendor": "V1",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V2",
    "ptype": "Gov",
    "critical": "low"
  },
  {
    "vendor": "V3",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V4",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V5",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V6",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V7",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V8",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V9",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V10",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V1",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V2",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V3",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V4",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V5",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V6",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V7",
    "ptype": "Gov",
    "critical": "low"
  },
  {
    "vendor": "V8",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V9",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V10",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V1",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V2",
    "ptype": "Gov",
    "critical": "low"
  },
  {
    "vendor": "V3",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V4",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V5",
    "ptype": "Non-Gov",
    "critical": "high"
  },
  {
    "vendor": "V6",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V7",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V8",
    "ptype": "Non-Gov",
    "critical": "low"
  },
  {
    "vendor": "V9",
    "ptype": "Gov",
    "critical": "high"
  },
  {
    "vendor": "V10",
    "ptype": "Gov",
    "critical": "low"
  }
]
  1. without rollup

     n = d3.nest().key(function(d){return d.vendor;})
        .key(function(d){return d.ptype;})
        .key(function(d){return d.critical;})
        .entries(j);
    
  2. with rollup

    n = d3.nest().key(function(d){return d.vendor;})
            .key(function(d){return d.ptype;})
            .key(function(d){return d.critical;})
            .rollup(function(leaf){
            return[
            {key:'GH', value:leaf[0].values.length}
            ,{key:'GL',value:leaf[1].values.length}
            ]})
            .entries(j);
    

2条回答
放荡不羁爱自由
2楼-- · 2019-09-14 17:26

i could do it this way..

var nested_data = d3.nest()
.key(function(d) { return d.vendor; }).sortKeys(d3.ascending)
.key(function(d) { return d.ptype; }).sortKeys(function(d) { return d;})
.key(function(d) { return d.critical; }).sortKeys(function(d) { return d;})
.rollup(function(leaves) { return leaves.length; })
.entries(j);

Thanks!

查看更多
甜甜的少女心
3楼-- · 2019-09-14 17:34

I don't know D3, but using vanilla JS you can transform the data as follows:

var input = [ { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "high" }, { "vendor": "V1", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V2", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V7", "ptype": "Gov", "critical": "low" }, { "vendor": "V8", "ptype": "Gov", "critical": "high" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "low" } ];

var working = input.reduce(function(p, c) {
    var v = p[c.vendor];
    if (!v) v = p[c.vendor] = {Gov: {high: 0, low: 0}, "Non-Gov": {high: 0, low: 0}};
    v[c.ptype][c.critical]++;
    return p;
  }, {});

var output = Object.keys(working).map(function(v) {
    var o = {};
    o[v] = working[v];
    return o;
  });

console.log(output);

Or if you can use ES6 syntax you can make the .map() part a lot shorter:

var input = [ { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "high" }, { "vendor": "V1", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V2", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V7", "ptype": "Gov", "critical": "low" }, { "vendor": "V8", "ptype": "Gov", "critical": "high" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "low" } ];

var working = input.reduce((p, c) => {
    var v = p[c.vendor];
    if (!v) v = p[c.vendor] = {Gov: {high: 0, low: 0}, "Non-Gov": {high: 0, low: 0}};
    v[c.ptype][c.critical]++;
    return p;
  }, {});

var output = Object.keys(working).map(v => ({ [v]: working[v] }));

console.log(output);

EDIT: It occurred to me that maybe you don't want to hard-code the possible ptype and critical values, so...the following (ugly, unoptimsed) version grabs the values as it goes:

var input = [ { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "high" }, { "vendor": "V1", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V2", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V7", "ptype": "Gov", "critical": "low" }, { "vendor": "V8", "ptype": "Gov", "critical": "high" }, { "vendor": "V9", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V1", "ptype": "Gov", "critical": "high" }, { "vendor": "V2", "ptype": "Gov", "critical": "low" }, { "vendor": "V3", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V4", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V5", "ptype": "Non-Gov", "critical": "high" }, { "vendor": "V6", "ptype": "Gov", "critical": "high" }, { "vendor": "V7", "ptype": "Gov", "critical": "high" }, { "vendor": "V8", "ptype": "Non-Gov", "critical": "low" }, { "vendor": "V9", "ptype": "Gov", "critical": "high" }, { "vendor": "V10", "ptype": "Gov", "critical": "low" } ];

var working = input.reduce((p, c) => {
    var v = p.vendors[c.vendor];
    if (!v) v = p.vendors[c.vendor] = {};
    if (!v[c.ptype]) v[c.ptype] = {};
    if (!v[c.ptype][c.critical]) v[c.ptype][c.critical] = 1;
    else v[c.ptype][c.critical]++;

    p.ptypes[c.ptype] = true;
    p.criticals[c.critical] = true;

    return p;
  }, {vendors:{}, ptypes:{}, criticals:{}});

var output = Object.keys(working.vendors).map(v => {
    var c = working.vendors[v];
    Object.keys(working.ptypes).forEach(p => {
      if (!c[p]) c[p] = {};
      Object.keys(working.criticals).forEach(q => c[p][q] || (c[p][q] = 0));
    });
    return { [v]: c };
  });

console.log(output);

查看更多
登录 后发表回答