创建键,值对JSON通过巢在D3

Create key, value pair for JSON via nest in D3

本文关键字:D3 JSON 值对 创建      更新时间:2023-09-26

我想使用d3.nest()为JSON创建一个键,值对。

原始JSON是这样的:

[
{
    "Country": "Mexico", 
    "Climate": 100,
    "Safety Index": 50,
    "Life Expectancy": 80,
    "Corruption": 30,
    "Per Capita Income": 20
},
{
    "Country": "UK",
    "Climate": 70,
    "Safety Index": 80,
    "Life Expectancy": 70,
    "Corruption": 70,
    "Per Capita Income": 80
},
{
    "Country": "US",
    "Climate": 80,
    "Safety Index": 70,
    "Life Expectancy": 90,
    "Corruption": 70,
    "Per Capita Income": 80
}
]

我想把它变成这样:

[
{"key": "Mexico", "value":
    [ 
        { "key": "Climate", "value": 100 },
        { "key": "Safety Index", "value": 50 },
        { "key": "Life Expectancy", "value": 80 },
        { "key": "Corruption", "value": 30 },
        { "key": "Per Capita Income", "value": 20 }
    ]},
{"key": "UK", "value":
    [ 
        { "key": "Climate", "value": 70 },
        { "key": "Safety Index", "value": 80 },
        { "key": "Life Expectancy", "value": 70 },
        { "key": "Corruption", "value": 70 },
        { "key": "Per Capita Income", "value": 80 }
    ]},
{"key": "US", "value":
    [ 
        { "key": "Climate", "value": 80 },
        { "key": "Safety Index", "value": 70 },
        { "key": "Life Expectancy", "value": 90 },
        { "key": "Corruption", "value": 70 },
        { "key": "Per Capita Income", "value": 80 }
    ]}
    ]

我的尝试:

var nest = d3.nest()
             .key(function(d) { return d.Country; })
             .entries(data);
我的问题是非常基本的,因为我是D3的新手。我该如何在D3中改变JSON的结构?

编辑

这是为了根据不同的类别为每个国家创建一个单独的条形图,类似于本示例(http://bl.ocks.org/mbostock/5872848)。如果有更好的方法来思考这个问题,请告诉我。

如果您想要得到您所提供的确切输出,并且坚持使用嵌套,您可以使用:

var nest = d3.nest()
         .key(function(d) { return d.Country; })
         .rollup(function(d) {
              var countryGroupedObject = d[0];
              return d3.nest()
                       .key(function(innerKey) { return innerKey; })
                       .rollup(function(innerKey) { return countryGroupedObject[innerKey]; })
                       .entries(Object.keys(countryGroupedObject));
          })
         .entries(data);

这里的一个潜在问题是,你假设每个国家都是唯一的(例如,不会有两个"墨西哥"条目)。因此,内巢只在d[0]上运行(这将是给定国家列出的第一个项目)。

Edit:实际上,这不会是完全您所要求的,国家键:值将存在于内部分组中。如果这是一个问题,可以通过在内部巢之前放置以下内容来忽略它:delete countryGroupedObject.Country;

编辑2:上面的代码使用嵌套的nest函数仅仅是因为问题是这样问的。在实际系统中,内部nest对我来说更有意义的是纯Javascript,沿着以下行:

function getGraphParams(countryObj){
    return Object.keys(countryObj)
                   .filter(function(key){ return key !== "Country"; })
                   .map(function(key){ return { key: key, value: countryObj[key] }; })
}

这是一个没有D3的解决方案:

var a = ...; // Original Array of JSON
var b = [];
a.forEach(function(item) {
    var r = {};
    r.key = item.Country;
    r.value = [];
    for (var i in item) {
        if (i === "Country") { continue; }
        r.value.push({"key": i, "value": item[i]});
    }
    b.push(r);
});

不知道为什么你只使用"键"作为你的键和"值"为你的值键虽然,这似乎违背了在JSON中使用隐式键和值的观点。但是我认为你这样做是有原因的。

你说:

如果有更好的方法来思考这个问题,请告诉我。

如果你要改变你的数据结构,为什么不把它变成这样呢?

[
    ["Mexico", 100, 50, 80, 30, 20],
    ["UK", 70, 80, 70, 70, 80],
    ["US", 80, 70, 90, 70, 80],
]

它要小得多,而且没有冗余。

如果您希望您的结构尽可能接近代码示例的数据结构,我仍然建议坚持使用您的原始数据结构,因为原始数据结构中的CSV文件被转换为与原始JSON文件的数据结构几乎相同的数据结构。