【问题标题】:d3.nest() key and values conversion to name and childrend3.nest() 键和值转换为名称和子项
【发布时间】:2013-06-29 06:22:36
【问题描述】:

我正在从 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":[.........`

我不能使用可缩放树形图,因为它需要 json 中的名称和子标签,而不是键和值。

【问题讨论】:

标签: javascript d3.js treemap


【解决方案1】:

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

在可缩放的树形图示例中,它不仅需要“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;
}

附:可能遗漏了什么,需要自己验证。

2) 转换您的 JSON 结构以适应带有 Array.map() 的示例。

【讨论】:

  • 是的,我想知道如何做 1) 更改可缩放树形图以使用键和值而不是名称和子级。我的数据很大,我不想解析结构只是为了更改标签。
  • 非常感谢,这真的很有帮助。虽然我无法让它完美地工作 jsfiddle.net/bvPUg/7。名称未显示。
  • 因为您的某些数据没有“密钥”,但他们的父母有。见jsfiddle.net/e9Ceb
【解决方案2】:

我完全同意 @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

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

【讨论】:

  • 这对我不起作用!当我将 treeData2 传递给我的分区的节点函数时,我的浏览器崩溃了!任何帮助将不胜感激..在 Firefox 中我遇到内存不足异常!
  • 听起来你的树结构中有一个循环。除此之外,我没有足够的信息来帮助你。
  • 我已经使用了这个解决方案,它对我有用,但我也在对离开节点进行计数。不幸的是,它也将计数标记为儿童,而我希望有一个不同的尺寸标签。我已经在这里发帖了,你能帮帮我吗..stackoverflow.com/questions/35120044
【解决方案3】:

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

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

然后使用 _.nest 函数创建您的结构。这是我的台词:

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

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

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

【讨论】:

    【解决方案4】:

    由于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>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 2020-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-06-23
      相关资源
      最近更新 更多