2017-05-29 9 views
0

d3.v3.min.jsを使用するHistogram chart using d3jsの例に基づいて、ヒストグラムも作成します。しかし、スニペットを呼び出すとき:値は(私のユースケースで発生する可能性があります)一つだけのユニークな値を持つ場合d3.layout.histogram().bins(...)(...)を呼び出すときに未定義のデータ問題を解決する方法

// Generate a histogram using twenty uniformly-spaced bins. 
var data = d3.layout.histogram() 
    .bins(x.ticks(20)) 
    (values); 
if (angular.isUndefined(data) || data.length === 0) { 
    // what now??? 
} 

をしては、上記のは、未定義のデータなどになりますいつvar values = [1., 1., 1., 1., 1., 1., 1.]

この境界線の場合、私は常に少なくとも1つの有効なビンを未定義のデータではなく確実に取得する方法がありますか?

更新日:この問題を再現するthe following JSFiddleを用意しました。コンソールを開いて、エラーと呼び出しスタックを確認してください。 IE F12またはFirefoxでDeveloper Toolsを使用します。

答えて

2

問題の根本原因はx.ticksを使用してビンを設定していることです。あなたは一つの値だけを持っている場合、これはminmaxが同じ値であることになり、あなたはここにはドメインがない:

var x = d3.scale.linear() 
    .domain([min, max]) 
    .range([0, width]); 

あなたは簡単なチェックでこれを防ぐことができます:

var max = d3.max(values); 
var min = d3.min(values); 
if (max === min){ 
    max += 0.1; 
    min -= 0.1; 
}  
var x = d3.scale.linear() 
     .domain([min, max]) 
     .range([0, width]); 

コードを実行する:

var color = "steelblue"; 
 

 
//var values = d3.range(1000).map(d3.random.normal(20, 5)); 
 
var values = d3.range(1000).map(function (idx) {return 1.0; }); 
 

 
// A formatter for counts. 
 
var formatCount = d3.format(",.0f"); 
 

 
var margin = {top: 20, right: 30, bottom: 30, left: 30}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var max = d3.max(values); 
 
var min = d3.min(values); 
 

 
if (max === min){ 
 
\t max += 0.1; 
 
    min -= 0.1; 
 
} 
 

 
var x = d3.scale.linear() 
 
     .domain([min, max]) 
 
     .range([0, width]); 
 

 
var data = d3.layout.histogram() 
 
    .bins(x.ticks(20)) 
 
    (values); 
 
    
 
    console.log(data) 
 

 
var yMax = d3.max(data, function(d){return d.length}); 
 
var yMin = d3.min(data, function(d){return d.length}); 
 
var colorScale = d3.scale.linear() 
 
      .domain([yMin, yMax]) 
 
      .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]); 
 

 
var y = d3.scale.linear() 
 
    .domain([0, yMax]) 
 
    .range([height, 0]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(x) 
 
    .orient("bottom"); 
 

 
var svg = d3.select("body").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
var bar = svg.selectAll(".bar") 
 
    .data(data) 
 
    .enter().append("g") 
 
    .attr("class", "bar") 
 
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 

 
bar.append("rect") 
 
    .attr("x", 1) 
 
    .attr("width", (x(data[0].dx) - x(0)) - 1) 
 
    .attr("height", function(d) { return height - y(d.y); }) 
 
    .attr("fill", function(d) { return colorScale(d.y) }); 
 

 
bar.append("text") 
 
    .attr("dy", ".75em") 
 
    .attr("y", -12) 
 
    .attr("x", (x(data[0].dx) - x(0))/2) 
 
    .attr("text-anchor", "middle") 
 
    .text(function(d) { return formatCount(d.y); }); 
 

 
svg.append("g") 
 
    .attr("class", "x axis") 
 
    .attr("transform", "translate(0," + height + ")") 
 
    .call(xAxis); 
 

 
/* 
 
* Adding refresh method to reload new data 
 
*/ 
 
function refresh(values){ 
 
    // var values = d3.range(1000).map(d3.random.normal(20, 5)); 
 
    var data = d3.layout.histogram() 
 
    .bins(x.ticks(20)) 
 
    (values); 
 

 
    // Reset y domain using new data 
 
    var yMax = d3.max(data, function(d){return d.length}); 
 
    var yMin = d3.min(data, function(d){return d.length}); 
 
    y.domain([0, yMax]); 
 
    var colorScale = d3.scale.linear() 
 
       .domain([yMin, yMax]) 
 
       .range([d3.rgb(color).brighter(), d3.rgb(color).darker()]); 
 

 
    var bar = svg.selectAll(".bar").data(data); 
 

 
    // Remove object with data 
 
    bar.exit().remove(); 
 

 
    bar.transition() 
 
    .duration(1000) 
 
    .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; }); 
 

 
    bar.select("rect") 
 
     .transition() 
 
     .duration(1000) 
 
     .attr("height", function(d) { return height - y(d.y); }) 
 
     .attr("fill", function(d) { return colorScale(d.y) }); 
 

 
    bar.select("text") 
 
     .transition() 
 
     .duration(1000) 
 
     .text(function(d) { return formatCount(d.y); }); 
 

 
}
body { 
 
    font: 10px sans-serif; 
 
} 
 

 
.bar rect { 
 
    shape-rendering: crispEdges; 
 
} 
 

 
.bar text { 
 
    fill: #999999; 
 
} 
 

 
.axis path, .axis line { 
 
    fill: none; 
 
    stroke: #000; 
 
    shape-rendering: crispEdges; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

関連する問題