d3.nest()键和值转换为name和children

时间:2013-07-02 01:44:20

标签: javascript d3.js treemap

我正在从csv文件创建一个Treemap。 csv文件中的数据是分层的,因此我使用d3.nest()

但是,生成的JSON采用{key:"United States", values:[...]}的形式。 可缩放treemap要求层次结构为{name:"United States", children:[...]}。 我已经尝试将名称和子项替换为示例中的键和值,但它不起作用。

如果有人已经考虑过在可缩放树形图上使用键和值,请提供帮助。我是D3的新手,我不知道d.children是否意味着数据的结构或价值。

这是使用d3将世界各大洲,地区和国家/地区从CSV转换为层次结构的代码。

$ d3.csv("../Data/WorldPopulation.csv", function (pop) {
    var treeData= { "key": "World", "values": d3.nest()
   .key(function (d) { return d.Major_Region; })
   .key(function (d) { return d.Region; })
   .key(function (d) { return d.Country; })
   .entries(pop)
};

结果的前几行是:

 `[{"key":"AFRICA","values":[{"key":"Eastern Africa","values"
 [{"key":"Burundi","values":[.........`

我无法使用zoomable treemap,因为它需要json中的name和children标签,而不是key和values。

4 个答案:

答案 0 :(得分:9)

将嵌套转换为树形图的最佳方法是使用Treemap.children()指定子访问器函数。

在zoomable treemap示例中,它不仅需要“children”,还需要“name”和“size”。你可以这样做:

1)更改这些属性的访问者功能,以便继续使用“key”和“value”。

让我们改变source code

1.1)第79行& 86:

 .style("fill", function(d) { return color(d.parent.name); });

 .text(function(d) { return d.name; })

将“.name”替换为“.YOUR_NAME_KEY”(即“.key”)

 .style("fill", function(d) { return color(d.parent.YOUR_NAME_KEY); });

 .text(function(d) { return d.YOUR_NAME_KEY; })

1.2)第47行:

var treemap = d3.layout.treemap()
.round(false)
.size([w, h])
.sticky(true)
.value(function(d) { return d.size; });

附加一行以指定子访问函数。(即“.values”)

var treemap = d3.layout.treemap()
.round(false)
.size([w, h])
.sticky(true)
.value(function(d) { return d.YOUR_SIZE_KEY; })
.children(function(d){return d.YOUR_CHILDREN_KEY});

1.3)第97行& 51:

function size(d) {
  return d.size;
}

将“.size”替换为“.YOUR_SIZE_KEY”(您在生成的JSON中未提及)

function size(d) {
  return d.YOUR_SIZE_KEY;
}

P.S。也许省略了一些东西,你需要自己验证一下。

2)将您的JSON结构转换为适合Array.map()的示例。

答案 1 :(得分:6)

我完全同意@Anderson这个问题的最简单方法是使用树形图children(function).value(function)方法来指定嵌套数据集中属性的名称。

然而,duplicate question has recently been posted提问者使用Array.map方法专门请求帮助。所以这就是:

array map(function) method创建一个新数组,其中数组中的每个元素都是在原始数组的每个元素上运行指定函数的结果。具体来说,该函数最多使用三个参数运行:原始数组中的元素,该元素的索引以及整个原始数组。出于操作属性名称的目的,我们只需要第一个参数。

原始帖子中的嵌套数据有三个级别,相当于三个关键功能。因此,我们需要一个三级映射函数:

var treeData = {
    "key": "World",
    "values": d3.nest()
        .key(function(d) {
            return d.Major_Region;
        })
        .key(function(d) {
            return d.Region;
        })
        .key(function(d) {
            return d.Country;
        })
        .entries(pop)
};

var treeData2 = {
    "name": "World",
    "children": treeData.values.map(function(major) {

        return {
            "name": major.key,
            "children": major.values.map(function(region) {

                return {
                    "name": region.key,
                    "children": region.values.map(function(country) {

                        return {
                            "name": country.key,
                            "children": country.values
                        };

                    }) //end of map(function(country){
                };

            }) //end of map(function(region){
        };

    }) //end of map(function(major){
}; //end of var declaration

您也可以使用递归函数实现此功能,如果您有更多级别的嵌套,这将特别有用。

答案 2 :(得分:2)

嘿伙计们,我想我找到了一个相当简单的解决方案。我以非常精简的方式为分层条形图完成了一个非常好的大数据集(400,000行)嵌套。它利用了Underscore库和一个附加功能_.nest。 只需下载并包含必要的两个库

“下划线min.js” “underscore.nest.js”

然后使用_.nest函数创建结构。这是我的专栏:

var newdata = _.nest(data, ["Material", "StudyName"]);

“Material”和“StudyName”是我要将结构分组到的列。

如果您需要完成更多的事情,还有其他选项可以使用此功能,但我会像这样离开

答案 3 :(得分:0)

由于不赞成使用d3-collection而推荐使用d3.array,因此我们可以使用d3.rollups来实现与d3.nest一起使用的功能:

var input = [
  { "Continent": "Europe", "Country": "Spain", "City": "Madrid", "value": "3" },
  { "Continent": "Europe", "Country": "Spain", "City": "Barcelona", "value": "30" },
  { "Continent": "Europe", "Country": "France", "City": "Paris", "value": "243" },
  { "Continent": "America", "Country": "Argentina", "City": "Buenos Aires", "value": "300" },
  { "Continent": "America", "Country": "Argentina", "City": "Buenos Aires", "value": "250" },
  { "Continent": "America", "Country": "Argentina", "City": "Rosario", "value": "200" }
];

// Nesting:
var rolled_up = d3.rollups(
  input,                           // The array on which to apply the rollup
  vs => d3.sum(vs, v => +v.value), // The reducing function to apply on rollups' leafs
  d => d.Continent,                // A first level of nesting
  d => d.Country                   // A second level of nesting
);

// Formatting:
var output = {
  key: "World",
  values: rolled_up.map(x => ({
    key: x[0], // continent
    values: x[1].map(x => ({
      key: x[0], // country
      values: x[1]
    }))
  }))
}

console.log(output);
<script src="https://d3js.org/d3-array.v2.min.js"></script>

此:

  • 应用d3.rollups
    • d3.rollups包含3个参数:输入数组,化简函数和可变数量的映射器,用于不同级别的嵌套
    • 归约函数(vs => d3.sum(vs, v => +v.value))提取与分组的国家/地区相关的值,将其转换为int并求和(使用d3.sum
    • 这两个级别的嵌套组元素首先在Continent上,然后在Country
  • 格式化汇总输出的每个嵌套部分,以获得预期的输出。

以下是d3.rollups产生的中间结果(在格式化之前):

var input = [
  { "Continent": "Europe", "Country": "Spain", "City": "Madrid", "value": "3" },
  { "Continent": "Europe", "Country": "Spain", "City": "Barcelona", "value": "30" },
  { "Continent": "Europe", "Country": "France", "City": "Paris", "value": "243" },
  { "Continent": "America", "Country": "Argentina", "City": "Buenos Aires", "value": "300" },
  { "Continent": "America", "Country": "Argentina", "City": "Buenos Aires", "value": "250" },
  { "Continent": "America", "Country": "Argentina", "City": "Rosario", "value": "200" }
];

var rolled_up = d3.rollups(
  input,
  vs => d3.sum(vs, v => +v.value),
  d => d.Continent,
  d => d.Country
);

console.log(rolled_up);
<script src="https://d3js.org/d3-array.v2.min.js"></script>