javascript - 循环遍历数据属性以创建 4 个单独的条形图...为什么会有 "phantom"数据元素绑定(bind)到 xAxis?

标签 javascript d3.js

我正在尝试制作一个四边形图表,其中每个象限包含一个条形图,描述一组 5 个数据对象的不同属性。类似于 **this** .

第一个图表正如我所料。问题是接下来三个图表的 x 轴。不知何故,有“幻影”数据元素被绑定(bind)到由 d3.svg.axis() 创建的 g 元素。在每种情况下,数据元素都是整数 0-4。
如下面的代码所示,我在自己的 svg 中创建每个条形图,并在一个循环中定义我可以定义的所有内容,在该循环中我遍历要绘制的属性列表。我这样做的原因是我的完整数据集每个对象大约有 20 个属性,但我一次只想绘制 4 个。另外,我不想重复只有一个参数不同的代码。

但我怀疑是 forEach 循环和 xAxis 函数中的某些东西导致了问题。

这是我的整个 js 文件:

var data = [{"name": "A", "engine_size": "1.6", "cmpg": "28", "horsepower": "103",  "msrp": "11690"}, 
{"name": "B", "engine_size": "1.6", "cmpg": "28", "horsepower": "103", "msrp": "12585"},
{"name": "C", "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14610"}, 
{"name": "D",  "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14810"},
{"name": "E",  "engine_size": "2.2", "cmpg": "26",  "horsepower": "140", "msrp": "16385"}];

var outer_width = 330,
    outer_height = 200,
    margin = {top: 10, right: 10, bottom: 10, left: 10},
    padding = {top: 20, right: 20, bottom: 20, left: 20},
    inner_width = outer_width - margin.left - margin.right,
    inner_height = outer_height - margin.top - margin.bottom,
    width = inner_width - padding.left - padding.right,
    height = inner_height - padding.top - padding.bottom;

var key = function(d) {
    return d.name;
}

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], 0.05);

var color = d3.scale.category20c();

var attribute_list = ['msrp', 'engine_size', 'horsepower', 'cmpg']; 
var svg = {};
attribute_list.forEach(function(entry) {
    svg[entry] = d3.select('.' + entry).append('svg')
    .attr('width', outer_width)
    .attr('height', outer_height)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
});

//d3.json('data/cars.json', function(error, data) {
    x.domain(data.map(key));
    xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom')
        .ticks(data.length);

    attribute_list.forEach(function(entry) {
        var g = svg[entry].append('g')
            .attr('transform', 'translate(0, ' + margin.bottom + ')')
            .append('g')
            .attr('class', 'axis')
            .attr('transform', 'translate(0, ' + height + ')')
            .call(xAxis);

        console.log(g.selectAll('line'));

        var y = d3.scale.linear()
            .domain([d3.min(data, function(d) { return +d[entry]; }),
                  d3.max(data, function(d) { return +d[entry]; })])
            .range([height*0.2, height*0.8]);   

        var bars = svg[entry].selectAll('rect')
            .data(data, key)
            .enter();

        bars.append('rect')
            .attr('class', 'bar')
            .attr('height', function(d) { return y(+d[entry]); })
            .attr('width', function(d) { return x.rangeBand(); })
            .attr('x', function(d, i) { return x(i); })
            .attr('y', function(d) { return height-y(+d[entry]); })
            .attr("fill", function(d){ return color(key(d)); });    
    }); 
//});

最佳答案

不确定您从哪里获得该输出,因为您提供的代码不会创建该输出。

您的代码片段在这里:

var data = [{"name": "A", "engine_size": "1.6", "cmpg": "28", "horsepower": "103",  "msrp": "11690"}, 
{"name": "B", "engine_size": "1.6", "cmpg": "28", "horsepower": "103", "msrp": "12585"},
{"name": "C", "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14610"}, 
{"name": "D",  "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14810"},
{"name": "E",  "engine_size": "2.2", "cmpg": "26",  "horsepower": "140", "msrp": "16385"}];

var outer_width = 330,
    outer_height = 200,
    margin = {top: 10, right: 10, bottom: 10, left: 10},
    padding = {top: 20, right: 20, bottom: 20, left: 20},
    inner_width = outer_width - margin.left - margin.right,
    inner_height = outer_height - margin.top - margin.bottom,
    width = inner_width - padding.left - padding.right,
    height = inner_height - padding.top - padding.bottom;

var key = function(d) {
    return d.name;
}

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], 0.05);

var color = d3.scale.category20c();

var attribute_list = ['msrp', 'engine_size', 'horsepower', 'cmpg']; 
var svg = {};
attribute_list.forEach(function(entry) {
    svg[entry] = d3.select('.' + entry).append('svg')
    .attr('width', outer_width)
    .attr('height', outer_height)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
});

//d3.json('data/cars.json', function(error, data) {
    x.domain(data.map(key));
    xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom')
        .ticks(data.length);

    attribute_list.forEach(function(entry) {
        var g = svg[entry].append('g')
            .attr('transform', 'translate(0, ' + margin.bottom + ')')
            .append('g')
            .attr('class', 'axis')
            .attr('transform', 'translate(0, ' + height + ')')
            .call(xAxis);

        console.log(g.selectAll('line'));

        var y = d3.scale.linear()
            .domain([d3.min(data, function(d) { return +d[entry]; }),
                  d3.max(data, function(d) { return +d[entry]; })])
            .range([height*0.2, height*0.8]);   

        var bars = svg[entry].selectAll('rect')
            .data(data, key)
            .enter();

        bars.append('rect')
            .attr('class', 'bar')
            .attr('height', function(d) { return y(+d[entry]); })
            .attr('width', function(d) { return x.rangeBand(); })
            .attr('x', function(d, i) { return x(i); })
            .attr('y', function(d) { return height-y(+d[entry]); })
            .attr("fill", function(d){ return color(key(d)); });    
    }); 
//});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class="msrp"></div>
<div class="engine_size"></div>
<div class="horsepower"></div>
<div class="cmpg"></div>

这是您的代码,它似乎在每个图形上生成一个左对齐的条形图,并且 X 轴看起来标记正确。每个图表实际上包含五个条形,但它们重叠。

这里是一些更正的代码:

var data = [{"name": "A", "engine_size": "1.6", "cmpg": "28", "horsepower": "103",  "msrp": "11690"}, 
{"name": "B", "engine_size": "1.6", "cmpg": "28", "horsepower": "103", "msrp": "12585"},
{"name": "C", "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14610"}, 
{"name": "D",  "engine_size": "2.2", "cmpg": "26", "horsepower": "140", "msrp": "14810"},
{"name": "E",  "engine_size": "2.2", "cmpg": "26",  "horsepower": "140", "msrp": "16385"}];


var outer_width = 330,
    outer_height = 200,
    margin = {top: 10, right: 10, bottom: 10, left: 10},
    padding = {top: 20, right: 20, bottom: 20, left: 20},
    inner_width = outer_width - margin.left - margin.right,
    inner_height = outer_height - margin.top - margin.bottom,
    width = inner_width - padding.left - padding.right,
    height = inner_height - padding.top - padding.bottom;

var key = function(d) {
    return d.name;
}

var x = d3.scale.ordinal()
    .rangeRoundBands([0, width], 0.05);

var color = d3.scale.category20c();

var attribute_list = ['msrp', 'engine_size', 'horsepower', 'cmpg']; 
var svg = {};
attribute_list.forEach(function(entry) {
    svg[entry] = d3.select('.' + entry).append('svg')
    .attr('width', outer_width)
    .attr('height', outer_height)
    .append('g')
    .attr('transform', 'translate(' + margin.left + ', ' + margin.top + ')');
});

//d3.json('data/cars.json', function(error, data) {
    x.domain(data.map(key));
    xAxis = d3.svg.axis()
        .scale(x)
        .orient('bottom')
        .ticks(data.length);

    attribute_list.forEach(function(entry) {
        var g = svg[entry].append('g')
            .attr('transform', 'translate(0, ' + margin.bottom + ')')
            .append('g')
            .attr('class', 'axis')
            .attr('transform', 'translate(0, ' + height + ')')
            .call(xAxis);

        console.log(g.selectAll('line'));

        var y = d3.scale.linear()
            .domain([d3.min(data, function(d) { return +d[entry]; }),
                  d3.max(data, function(d) { return +d[entry]; })])
            .range([height*0.2, height*0.8]);   

        var bars = svg[entry].selectAll('rect')
            .data(data, key)
            .enter();

        bars.append('rect')
            .attr('class', 'bar')
            .attr('height', function(d) { return y(+d[entry]); })
            .attr('width', function(d) { return x.rangeBand(); })
            .attr('x', function(d, i) { return x(d.name); })
            .attr('y', function(d) { return height-y(+d[entry]); })
            .attr("fill", function(d){ return color(key(d)); });    
    }); 
//});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div class="msrp"></div>
<div class="engine_size"></div>
<div class="horsepower"></div>
<div class="cmpg"></div>

您正在为每个柱计算您的 X 位置:

.attr('x', function(d, i) { return x(i); })

我认为您实际上想计算每个柱的 X 位置:

.attr('x', function(d, i) { return x(d.name); })

您传入的索引不是为 X 比例定义的域的一部分,它将返回未定义。传递名称意味着您传递的值是域的一部分,因此您将获得相应的坐标。

关于javascript - 循环遍历数据属性以创建 4 个单独的条形图...为什么会有 "phantom"数据元素绑定(bind)到 xAxis?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26029141/

相关文章:

angular - 如何使用 Angular 2 和 Typescript 实现 D3 套索插件

Javascript - 无法访问从 csv 文件创建的数组的数组元素

javascript - 在圆之间绘制路径

javascript - css 动画仅在元素失去焦点时触发

php - Ajax + PHP 登录脚本不起作用

JavaScript 移动应用能力

d3.js - 在 d3.js 或 nvd3.js 线图中选择一条线

javascript - Ajax、JS 和 "-"的

javascript - 如何将日期与今天的日期进行比较?其中日期的格式为 dd-mm-yyyy?

d3.js - 如何使用 d3 在散点图中绘制两个轴的正值和负值?