d3过滤后无法附加完整数据 [英] d3 unable to append full data after filtering

查看:55
本文介绍了d3过滤后无法附加完整数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个项目的简化版本,我将其压缩到以下代码段中:

I have a simplified version of my project that I condensed into this snippet:

var margins = {top:20, bottom:300, left:100, right:100};

var height = 600;
var width = 1200;

var totalWidth = width+margins.left+margins.right;
var totalHeight = height+margins.top+margins.bottom;

var svg = d3.select('body')
    .append('svg')
    .attr('width', totalWidth)
    .attr('height', totalHeight);

var graphGroup = svg.append('g')
    .attr('transform', "translate("+margins.left+","+margins.top+")");

var data = [
  {'manager':'ABC-CA', 'aum':230561804112.86996, 'type':'JV'},
  {'manager':'AEGON-Industrial', 'aum':187676730861.82004, 'type':'JV'},
  {'manager':'AVIC', 'aum':677643221.8599999, 'type':'DM'},
  {'manager':'AXA-SPDB', 'aum':111220010833.66998, 'type':'JV'},
  {'manager':'Baoying', 'aum':26328526612.41, 'type':'DM'},
  {'manager':'Beixin Ruifeng', 'aum':10500065729.3, 'type':'JV'},
  {'manager':'BOB-Scotiabank', 'aum':69159188249.67, 'type':'JV'},
  {'manager':'BOC IM', 'aum':396466612963.73, 'type':'DM'},
  {'manager':'BOCI Securities', 'aum':57940275708.97, 'type':'JV'}
];

  var yExtents = d3.extent(data, function(d) {return d.aum; })

  var xScale = d3.scaleBand()
    .rangeRound([0, width])
    .domain(data.map(function(d) {return d.manager; }));

  var yScale = d3.scaleLinear()
      .range([height,0])
      .domain(yExtents);

  graphGroup.append("g")
      .attr("class", "axis axis--y")
      .attr("transform", "translate(0," + 0 + ")")
      .call(d3.axisRight(yScale))
      .selectAll("text")
      .attr('text-align','right')
      .attr("transform", "translate(-90,0)");

  graphGroup.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .call(d3.axisBottom(xScale))
      .selectAll("text")
      .attr("transform", "translate(0,0)");


  var bars = graphGroup.selectAll('rect')
    .data(data)
    .enter()
    .append('rect')
    .attr('x', function(d) {return xScale(d.manager); })
    .attr('y', function(d) {return yScale(d.aum); })
    .attr('width', xScale.bandwidth())
    .attr('height', function(d) {return height-yScale(d.aum); })
    .style('fill','#003366');

  d3.select('#rd1').on('click', function() {

    var newData = data;

    bars.data(newData).enter()
        .append('rect');

    bars.transition()
        .duration(750)
        .attr('x', function(d) {return xScale(d.manager); })
        .attr('y', function(d) {return yScale(d.aum); })
        .attr('height', function(d) {return height-yScale(d.aum); })
        .style('fill','#003366');

  });

  d3.select('#rd2').on('click', function() {

    var newData = data.filter(function(d) {return d.type=="JV"});
    bars.data(newData).exit().remove();

    bars.enter()
        .attr('x', function(d) {return xScale(d.manager); })
        .attr('y',height);

    bars.transition()
        .duration(750)
        .attr('x', function(d) {return xScale(d.manager); })
        .attr('y', function(d) {return yScale(d.aum); })
        .attr('height', function(d) {return height-yScale(d.aum); });

  });

<form>
<label class='radio-label'>All <input type="radio" name="level" value="all" checked="checked" id='rd1'></input></label>
<label class='radio-label'>JV <input type="radio" name="level" value="jv" id='rd2'></input></label>
</form>
<script src="https://d3js.org/d3.v5.min.js"></script>

我的目的是当用户单击合资"单选按钮时,按d.type=='JV'过滤数据,并且可以完成很多工作.但是,我对所有"单选按钮的功能无法按我预期的那样工作,并且对它的故障排除已证明存在问题. 所有"单选按钮应该再次显示整个数据集,但它仅显示数据集的一部分,因此缺少值,我不知道如何正确设置.

My intent is to filter the data by d.type=='JV' when the user clicks on the "JV" radio button, and that much works. However, my function for the "All" radio button doesn't work as I anticipated and troubleshooting it has proven problematic. The "All" radio button is supposed to display the whole data set again, but it only displays part of the data set, so it's missing values and I can't figure out how to make it right.

在控制台日志中,console.log(newData.length)是正确的数字:9,但仅附加了5个区域.

In the console log the console.log(newData.length) is the correct number: 9, but there are only 5 rects appended.

我的输入,更新,退出实现是否有缺陷,如果存在,如何解决,以便在过滤后可以再次完整显示我的数据?

Is my enter, update, exit implementation flawed, and if so, how do I fix it such that my data can be displayed in full again after filtering?

推荐答案

var margins = {
  top: 20,
  bottom: 300,
  left: 100,
  right: 100
};

var height = 600;
var width = 1200;

var totalWidth = width + margins.left + margins.right;
var totalHeight = height + margins.top + margins.bottom;

var svg = d3.select('body')
  .append('svg')
  .attr('width', totalWidth)
  .attr('height', totalHeight);

var graphGroup = svg.append('g')
  .attr('transform', "translate(" + margins.left + "," + margins.top + ")");

var data = [{
    'manager': 'ABC-CA',
    'aum': 230561804112.86996,
    'type': 'JV'
  },
  {
    'manager': 'AEGON-Industrial',
    'aum': 187676730861.82004,
    'type': 'JV'
  },
  {
    'manager': 'AVIC',
    'aum': 677643221.8599999,
    'type': 'DM'
  },
  {
    'manager': 'AXA-SPDB',
    'aum': 111220010833.66998,
    'type': 'JV'
  },
  {
    'manager': 'Baoying',
    'aum': 26328526612.41,
    'type': 'DM'
  },
  {
    'manager': 'Beixin Ruifeng',
    'aum': 10500065729.3,
    'type': 'JV'
  },
  {
    'manager': 'BOB-Scotiabank',
    'aum': 69159188249.67,
    'type': 'JV'
  },
  {
    'manager': 'BOC IM',
    'aum': 396466612963.73,
    'type': 'DM'
  },
  {
    'manager': 'BOCI Securities',
    'aum': 57940275708.97,
    'type': 'JV'
  }
];

var yExtents = d3.extent(data, function(d) {
  return d.aum;
})

var xScale = d3.scaleBand()
  .rangeRound([0, width])
  .domain(data.map(function(d) {
    return d.manager;
  }));

var yScale = d3.scaleLinear()
  .range([height, 0])
  .domain(yExtents);

graphGroup.append("g")
  .attr("class", "axis axis--y")
  .attr("transform", "translate(0," + 0 + ")")
  .call(d3.axisRight(yScale))
  .selectAll("text")
  .attr('text-align', 'right')
  .attr("transform", "translate(-90,0)");

graphGroup.append("g")
  .attr("class", "axis axis--x")
  .attr("transform", "translate(0," + height + ")")
  .call(d3.axisBottom(xScale))
  .selectAll("text")
  .attr("transform", "translate(0,0)");

function applyData(newData) {
  var bars = graphGroup
    .selectAll('rect')
    .data(newData);

  bars.exit().remove();

  bars.enter()
    .append('rect')
    .attr('x', function(d) {
      return xScale(d.manager);
    })
    .attr('y', height)    
    .attr('width', xScale.bandwidth())
    .style('fill', '#003366')
    .merge(bars)
    .transition()
    .duration(750)
    .attr('x', function(d) {
      return xScale(d.manager);
    })
    .attr('y', function(d) {
      return yScale(d.aum);
    })
    .attr('height', function(d) {
      return height - yScale(d.aum);
    });
}

d3.select('#rd1').on('click', function() {
  applyData(data);
});

d3.select('#rd2').on('click', function() {

  var newData = data.filter(function(d) {
    return d.type == "JV"
  });
  applyData(newData);

});

applyData(data);

<form>
  <label class='radio-label'>All <input type="radio" name="level" value="all" checked="checked" id='rd1'></input></label>
  <label class='radio-label'>JV <input type="radio" name="level" value="jv" id='rd2'></input></label>
</form>
<script src="https://d3js.org/d3.v5.min.js"></script>

选择是不可变的-您不能在不同的data调用之间保存和重用bars选择.另外,您将在3个地方复制代码-初始数据和每个点击处理程序.我通过将代码提取为一种方法来重构您的代码.

Selections are immutable -- you cannot save and reuse bars selection in between different data invokes. Also, you're duplicating your code in 3 places -- initial data and in each of the click handlers. I refactored your code by extracting it into one method.

这篇关于d3过滤后无法附加完整数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆