在d3.js

时间:2015-11-07 05:24:48

标签: javascript d3.js data-visualization

我目前正在尝试从CSV文件制作一系列简单的条形图。 CSV文件分为多个列,每个列代表一个调查问题。每行代表一个调查受访者,每个单元格是特定问题的特定问题的答案。

这个想法是在顶部有一个两个箭头按钮,允许我更改图表,以便它代表调查中的下一个问题。

当我第一次加载页面时,我可以加载任何给定的图表,但是当我尝试使用按钮时,我会得到非常奇怪的行为,有些条不会消失,有些条会与其他条加倍。

例如,它可能会像这样开始: enter image description here

按下几个按钮后,这两个轴和杆都加倍了:

enter image description here

我怀疑我正在严格分配密钥,以便d3不知道需要删除的内容,但我无法理解其中的内容。这是代码:

<!DOCTYPE html>
<html>
    <head>
      <meta charset="utf-8">
      <script src="http://d3js.org/d3.v3.min.js"></script>
      <style>
      </style>
      <script type="text/javascript">
        function draw(data) {
            "use strict";

            // Sets up initial question
            var current_question = [1];

            /*sets up the canvas for the visualization*/
            var margin = 75,
            width = 1400 - margin,
            height = 700 - margin;

            /*Adds title*/
            d3.select("body")
              .append("h2")
              .text("Environmental Attitudes");

            //Adds space for updated question text later
            var question_text = d3.select("body")
                                  .append('div')
                                  .attr('class','question_text');

            /*Adds buttons for question selection*/
            var buttons =d3.select("body")
                           .append('div')
                           .attr('class','question_selection_buttons');



            // y scale
            var y = d3.scale.linear()
                            .range([height,0]);
            // x scale
            var x = d3.scale.ordinal()
                      .rangeRoundBands([0, width], .1);
            //x axis
            var xAxis = d3.svg.axis()
                              .scale(x)
                              .orient("bottom");
            //y axis
            var yAxis = d3.svg.axis()
                              .scale(y)
                              .orient("left");

            /*Adds the SVG element that will house everything else*/
            var svg = d3.select("body")
                        .append("svg")
                        .attr("id", "svg_main")
                        .attr("width", width + margin)
                        .attr("height", height + margin);

            // list of variables
            var questions = d3.keys(data[0]).filter(function(d){
                                                        var x = "cluster";
                                                        if (d.indexOf(x) === -1 && d !== 'ids') {
                                                            return d    ;
                                                        }       
                                                    });

            var num_questions = questions.length;

            function update_chart(question) {

                /*
                d3.selectAll("svg > *")
                          .remove();
                */
                // filters out NaN observations from data from the question "question"
                var new_data = data.filter(function(d){
                    if(isNaN(+d[question])){
                        return false;
                    }
                    return true;
                });


                // rolls up data by answer in "question"
                var nested = d3.nest()
                               .key(function(d){return d[question];
                               })
                               .rollup(function(leaves){
                                    var total = data.length
                                    var responses = leaves.length;

                                    return {
                                        'responses' : responses,
                                        'percent' : responses/total
                                    };
                                })
                               .entries(new_data)

                var elem = svg.selectAll('rect')
                              .data(nested)
                              .exit()
                              .remove();

                //sets the domain of x by passing it the range of possible values
                x.domain(nested.map(function (d) {
                    return d.key;
                }));

                //sets the domain of y by passing it the range of possible values
                y.domain([0, d3.max(nested, function (d) {
                    return +d.values['percent'].toPrecision(3);
                })]);
                //draws x axis
                svg.append("g")
                   .attr('class','x axis')
                   .attr('transform', 'translate(0,' + height + ')')
                   .call(xAxis);
                //draws y axis
                svg.append('g')
                   .attr("class", 'y axis')
                   .call(yAxis);

                svg.selectAll('g')
                   .data(nested)
                   .enter().append('g')
                   .attr('class','response')
                   .attr('transform', function(d){
                        return "translate (" + x(d.key) + ",0)";
                    });


                svg.selectAll('rect')
                        .data(nested)
                        .enter().append("rect")
                        .attr("width", x.rangeBand())
                        .attr('height', function(d){

                            return height-y(+d.values['percent'].toPrecision(3));
                        })
                        .attr("y", function(d){return y(+d.values['percent'].toPrecision(3))})
                        .attr('transform', function(d){
                            return "translate (" + x(d.key) + ",0)";
                        });



            };


            var left = buttons.append('div')
                              .selectAll('div')
                              .data(current_question)
                              .enter()
                              .append('div')
                              .attr("class", "button")
                              .text("<")
                              .attr("id", "left-button");

            var right = buttons.append('div')
                               .selectAll('div')
                               .data(current_question)
                               .enter()
                               .insert('div')
                               .attr("class", "button")
                               .text(">")
                               .attr("id", "right-button");

            left.on("click", function(d) {
                    current_question--
                    if (current_question < 0) {
                        current_question = num_questions-1;
                    };
                    update_chart(questions[current_question])
                });
            right.on("click", function(d) {
                    current_question++
                    if (current_question >= num_questions) {
                        current_question = 0
                    }

                    update_chart(questions[current_question]);
                });

            update_chart(questions[current_question[0]]);


        }
      </script>
    </head>
    </body>
        <script type="text/javascript">
            d3.csv("clusterData.csv", draw)
        </script>
    </body>
</html>

再说一遍。通过在每次更新时清除svg元素的所有内容,我已经使图表正确刷新。该代码在上面的代码中被注释掉了。我想通过使用来做到这一点     .exit()。除去()。

Here is a sample of the data

以下是CSV格式的较小数据片段:

ids,ldcgrn,othssame,chemgen,natchld,natpark,sex,nukegen,harmgood,topprob1,drivless,grnmoney,topprob2,peopgrn,natsci,grngroup,redcehme,grntaxes,grncon,govdook,knowsol,chemfree,ihlpgrn,tempgen1,recycle,grndemo,impgrn,scigrn,h2oless,carsgen,indusgen,grnprice,grwthelp,nobuygrn,grneffme,helpharm,grnprog,toodifme,grnsign,harmsgrn,grnexagg,popgrwth,watergen,natenrgy,busgrn,natsoc,privent,grnsol,natroad,age,usdoenuf,grwtharm,econgrn,race,polgreed,polviews,grnintl,knwcause,grnecon,2_clusters,3_clusters,4_clusters,5_clusters,6_clusters,7_clusters,8_clusters,9_clusters,
1269,2,3,3,2,2,Female,1,4,Poverty,NaN,0,Health care,More information and education for people about the advantages of protecting the environment,2,0,1,4,3,4,3,1,4,3,NaN,0,3,3,1,3,2,3,3,1,NaN,4,4,4,0,4,3,4,3,2,More information and education for businesses about the advantages of protecting the environment,2,NaN,5,2,71,2,3,3,Black,4,6,3,3,3,1,0,1,0,5,6,2,0,
1403,4,2,3,1,1,Male,3,2,Health care,2,0,The environment,Heavy fines for people who damage the environment,2,0,2,3,5,3,4,2,4,3,2,0,4,4,2,1,1,2,4,4,2,3,4,5,0,4,4,4,1,2,NaN,2,4,3,2,18,2,2,4,Black,2,4,5,5,2,1,1,2,3,0,0,3,7,
1868,4,4,2,1,1,Male,1,2,The economy,NaN,0,Health care,More information and education for people about the advantages of protecting the environment,2,0,2,2,5,NaN,1,1,2,3,3,0,4,4,2,1,1,2,4,2,4,4,4,4,0,4,4,4,2,3,Heavy fines for businesses that damage the environment,2,5,4,2,51,1,2,4,White,4,4,4,1,3,1,1,1,3,0,0,3,7,
1296,2,2,2,1,1,Female,NaN,4,Health care,2,0,Immigration,More information and education for people about the advantages of protecting the environment,NaN,0,2,4,5,1,3,3,5,3,4,0,3,3,2,4,3,2,3,3,4,4,NaN,2,0,3,3,4,1,1,Heavy fines for businesses that damage the environment,1,3,2,NaN,41,1,3,NaN,White,4,4,4,3,2,0,1,2,2,3,2,7,4,
1256,2,4,2,1,2,Male,5,2,The economy,NaN,0,Poverty,More information and education for people about the advantages of protecting the environment,2,0,3,5,5,4,2,3,4,4,2,0,4,3,3,2,3,4,5,3,4,4,5,1,0,5,3,3,3,1,More information and education for businesses about the advantages of protecting the environment,1,3,5,1,51,2,2,4,Black,2,5,4,3,5,1,0,1,3,1,3,4,2,
1943,2,4,3,1,2,Female,2,1,Immigration,2,0,The economy,More information and education for people about the advantages of protecting the environment,1,0,2,5,5,2,2,2,4,3,3,0,3,2,3,1,1,2,4,2,5,4,2,4,0,4,2,4,1,1,More information and education for businesses about the advantages of protecting the environment,1,2,2,2,52,1,3,3,White,4,7,4,2,1,0,1,2,2,3,2,7,4,
1940,2,2,3,2,2,Male,3,2,Terrorism,3,0,Poverty,Use the tax system to reward people who protect the environment,1,0,3,3,4,2,2,3,4,1,4,0,2,2,2,2,2,3,4,2,2,4,4,4,0,4,2,4,1,1,Use the tax system to reward businesses that protect the environment,1,2,5,2,47,2,2,4,White,3,4,4,2,2,0,1,2,2,3,3,7,2,
1941,2,4,4,1,2,Male,4,2,Health care,1,0,Crime,More information and education for people about the advantages of protecting the environment,2,0,2,5,1,4,2,3,4,1,3,0,4,2,2,1,2,4,4,2,2,2,2,4,0,2,4,4,1,2,Heavy fines for businesses that damage the environment,2,2,5,2,75,1,2,4,White,2,3,4,2,4,1,0,1,0,5,6,2,2,

1 个答案:

答案 0 :(得分:1)

夫妻问题:

1。)您将在每次更新时重新附加轴。添加一个空白,然后每次更新。

2。)您的rects根本没有关注输入,更新,退出模式。请参阅下文,了解我如何相互独立地处理输入,更新和退出。

// set x domain to new data
x.domain(nested.map(function (d) {
    return d.key;
}));

// set y domain to new data
y.domain([0, d3.max(nested, function (d) {
    return +d.values['percent'].toPrecision(3);
})]);

// select your rects and bind your data
// note how I'm giving it a "key" function to guarantee the join is computed properly (https://github.com/mbostock/d3/wiki/Selections#data)
var rects = svg.selectAll('rect')
  .data(nested, function(d){
    return d.key;
  });

// handle those elements entering
rects
  .enter().append("rect");

// handle the update
rects
  .attr("width", x.rangeBand())
  .attr('height', function(d){
      return height-y(+d.values['percent'].toPrecision(3));
  })
  .attr("y", function(d){return y(+d.values['percent'].toPrecision(3))})
  .attr('x', function(d){
      return x(d.key);
  });

// handle the exit
rects.exit().remove();

// just update an already existing axis
svg.select('g.x.axis')
  .call(xAxis);

svg.select('g.y.axis')
  .call(yAxis);

Here's a working example where I've cleaned up your code a bit.