【问题标题】:Associative arrays and using parent d as a source array for selection.data()关联数组并使用 parent d 作为 selection.data() 的源数组
【发布时间】:2012-08-21 14:26:21
【问题描述】:

我正在尝试从一些 csv 数据创建堆积条形图。阅读了 Scott Murray 的教程 http://alignedleft.com/tutorials/d3/ (顺便说一句:这是我遇到的关于 d3.js 的最佳教程,应该真正链接到 d3 wiki 上),以及 Andrew Davis 的教程,我将以下内容汇总在一起试用代码来创建我需要的矩形:

window.onload = function()
{
var LikertData = [{a:0,b:1},{a:0,b:1},{a:0,b:1},{a:0,b:1},];
var w = 200;
var h = 200;

var svg = d3.select("body").append("svg")
        .attr("width", w)
        .attr("height", h);

var myG  = svg.selectAll("g")
        .data(LikertData)
        .enter()
        .append("g")
        .text(function(d)
        {
        var myRect = d3.selectAll("rect")
        .data(d.entries)
        .enter()
        .append("rect");
        return myRect;
            });
}

这个想法是,对于形成 LikertData 数组的每个数组,将一个矩形添加到父 g 元素。但是,它不起作用。我是不是有点暖和了?

编辑:这更接近我想要的 - 我已经指出了让我难过的 .data 以及我想要用于数据的内容:

window.onload = function()
{
    d3.csv("likert.csv", function(LikertData){
        var svg = d3.select("body").append("svg")

        var myG  = svg.selectAll("g")
            .data(LikertData)
            .enter()
            .append("g")
            .selectAll("rect")
            .data()//<--I want data to use an array of key values for the parent g's d
            .enter()
            .append("rect");
    });
}

使用 console.log(d3.entries(LikertData)) 产生多个对象,如下所示 - 因此数据是关联的:

[
Object
    key: "50"
    value: Object
        Agree: ""
        Always: "39.1%"
        Disagree: ""
        Neutral: ""
        Never: "4.3%"
        Row Labels: "I run out of time in long tasks"
        Sometimes: "52.2%"
        Strongly Agree: ""
        Strongly Disagree: ""
        Unanswered: "4.3%"
        __proto__: Object
    __proto__: Object
]

【问题讨论】:

    标签: javascript json d3.js binding


    【解决方案1】:

    不要太远。试试

    var LikertData = [{a:0,b:1},{a:0,b:1},{a:0,b:1},{a:0,b:1},];
    var w = 200; var h = 200; 
    
    var svg = d3.select("body").append("svg")
      .attr("width", w)
      .attr("height", h);
    
    var myG  = svg.selectAll("rect")
      .data(LikertData).enter()
      .append("rect")
      .attr("x", function(d, i) { return i * 50; })
      .attr("y", function(d, i) { return i * 50; })
      .attr("width", 50)
      .attr("height", 50);
    

    xy 属性定位矩形,您需要为它们指定宽度和高度。如果您想将它们包装在 g 元素中,只需在调用 data() 之前添加 .append("g") - 不过这里没有必要。

    text 函数只能用于设置文本内容——不要用它来添加新元素。您也没有嵌套数组,因此您只需调用一次.data()

    【讨论】:

    • 那不是我害怕之后的样子。问题是 csv 导入将为您提供 csv 文件的列作为每行的键值。我想得到这样的结果:&lt;g class="row1"&gt; &lt;rect "key1" /&gt; &lt;rect "key2" /&gt; &lt;rect "key3" /&gt; &lt;/g&gt; &lt;g class="row2"&gt; &lt;rect "key1" /&gt; &lt;rect "key2" /&gt; &lt;rect "key3" /&gt; &lt;/g&gt;
    • 然后,您需要将您提供的数据嵌套在每行的单独数组中。请查看this tutorial 了解更多详情。
    • 我以前看过嵌套。问题是我不想基于键值嵌套我的数据 - 我想实际使用键值作为 .data() 的数组。我已经编辑了上面的代码并显示了一个控制台输出,它应该使事情更清楚。感谢您迄今为止的想法@Lars
    • 好的,现在你有一个对象列表。您可以将其传递给.data() 为这些对象中的每一个添加元素,但您希望将它们组织成行(这可能是由数据中的某些内容决定的)。虽然你可以只用一个平面数组来做到这一点,但使用 d3 拥有一个数组数组会更“自然”——而不是一个平面对象列表,你有一个对象列表。单个对象仍将拥有所有信息,但您可以进行两次.data() 调用——一个用于行,一个用于每行中的对象。
    • 最后想出了一个更简单的解决方法:使用 parseRows 解析 csv 以创建一个数组数组,允许我在箭头标记的点处使用 function(d){return d} 作为数据源。感谢您的所有帮助。
    【解决方案2】:

    最终代码简化 - 更改 csv 的解析方式以使用 parseRows 函数导致创建了一个数组数组,允许我将外部 d 作为 .data 的源:

    window.onload = function()
    {   
        d3.text("likert.csv", function(LikertData){
            var parsedData = d3.csv.parseRows(LikertData);
    
            var svg = d3.select("body")
            .append("svg");
    
            var g = svg.selectAll("g")
            .data(parsedData)
            .enter()
            .append("g");
    
            var gRect = g.selectAll("rect")
                .data(function(d){return d})
                .enter()
                .append("rect");
    
        });
    }
    

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 2016-07-03
      • 1970-01-01
      • 2016-02-17
      相关资源
      最近更新 更多