Why does the domain not use d3.max (data) in D3?

I am new to D3 and playing with a scatter chart. I can not get d3.max (data) to work correctly when setting up a domain!

I have the following setting for a random data set:

var data = []; for (i=0; i < 40; i++){ data.push({"x": i/40, "y": i/8, "a": Math.floor(Math.random() * 3), "x2": Math.random()}); } 

And then to set the coordinates:

  var x = d3.scale.linear().domain([0, 1]).range([0 + margin, w-margin]), y = d3.scale.linear().domain([0, d3.max(data)]).range([0 + margin, h-margin]), c = d3.scale.linear().domain([0, 3]).range(["hsl(100,50%,50%)", "rgb(350, 50%, 50%)"]).interpolate(d3.interpolateHsl); 

This puts all 40 points in one horizontal line. If I replaced d3.max (data) with "5", then this is the diagonal (although from the upper left corner to the right to the right, I'm still trying to flip the y-coordinates). Why is d3.max (data) working as expected?

+6
source share
3 answers

d3.max() expects an array of numbers, not objects. The data elements have an internal key value structure, and there is no way for d3.max() to know what to take the maximum. You can use something like jQuery $.map to get the elements of the required objects and then take max, for example.

 var maxy = d3.max($.map(data, function(d) { return dy; })); 

Edit:

As stated in the comment below, you don’t even need jQuery, since .map() is its own Array method. Then the code just becomes

 var maxy = d3.max(data.map(function(d) { return dy; })); 

or even simpler (and for those browsers that do not implement Array.map() ), using the optional second argument d3.max , which tells it how to access the values ​​in the array

 var maxy = d3.max(data, function(d) { return dy; }); 
+9
source

d3.max API documentation can be found here .

# d3. max (array [, accessor])

Returns the maximum value in the given array using natural order. If the array is empty, returns undefined. An additional access function can be specified, which is equivalent to calling array.map (accessor) before calculating the maximum value. Unlike the built-in Math.max, this method ignores undefined values; this is useful for calculating the area of ​​the scale, but only given a certain area of ​​data. In addition, elements are compared using a natural order rather than a numerical order. For example, the maximum ["20", "3"] is "3", while the maximum [20, 3] is 20.

Applying this information to the original question, we get:

 function accessor(o){ return oy; } var y = d3.scale.linear() .domain([0, d3.max(data, accessor)]) .range([0 + margin, h-margin]); 

If you end up using many access functions, you can just make a factory.

 function accessor(key) { return function (o) { return o[key]; }; } var x = d3.scale.linear() .domain([0, d3.max(data, accessor('x'))]) .range([...]), y = d3.scale.linear() .domain([0, d3.max(data, accessor('y'))]) .range([...]); 
+3
source

I had a similar problem with an associative array. My data was as follows: [{"year_decided": 1982, "total": 0}, {"year_decided": "1983", "Total": "847"}, ...}]

Just pass parseInt before returning the resulting value.

 var yScale = d3.scale.linear() .domain([0, d3.max(query,function(d){ return parseInt(d["Total"]); }) ]) .range([0,h]); 
0
source

Source: https://habr.com/ru/post/910615/


All Articles