I have an external csv file with data in columns like so:
name, field_goal_attempts, field_goal_makes
I am trying to use a linear scale but am encountering difficulty getting the maximum value for my domain.
var yScale = d3.scale.linear()
.domain(0, d3.max(...
I am confused as to:
1) Whether I should put the yScale function outside or inside the
d3.csv("filename.csv", function(data) {
callback function; and
2) How to get the maximum value of items in the field_goal_attempts column to then feed into the yScale function.
Here is my code at present:
var yScale = d3.scale.linear()
.domain([0, 4000]) //d3.max(data, function(d) {return d })])
.range([0, 500]);
d3.csv("test.csv", function (data) {
svg.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("fill", "blue")
.attr("x", magic_number) // I'm not concerned about the magic numbers at this point :)
.attr("y", 0)
.attr("width", another_magic_number)
.attr("height", function (d) {
return d.field_goal_attempts
})
.attr("id", function (d, i) {
return i
});
});
min is d3. max, which returns the maximum value.
The d3. scaleLinear() method is used to create a visual scale point. This method is used to transform data values into visual variables.
D3 has around 12 different scale types (scaleLinear, scalePow, scaleQuantise, scaleOrdinal etc.) and broadly speaking they can be classified into 3 groups: scales with continuous input and continuous output. scales with continuous input and discrete output. scales with discrete input and discrete output.
The data in your csv file will be in the callback you pass to the csv function (in your case the "data" parameter). So you can define yScale outside of the csv function, but if you want the max to be data dependent you will need to set it inside the callback.
As for finding the max, many D3 functions that work on arrays will accept optional accessor functions for precisely your scenario. So computing the max I would use:
var max = d3.max(data, function(d) { return +d.field_goal_attempts;} );
So you could put it all together one of two ways:
var yScale = d3.scale.linear().domain(0,100);
d3.csv("test.csv", function(data){
var max = d3.max(data, function(d) { return +d.field_goal_attempts;} );
yScale.domain([0,max]);
...
}
or
d3.csv("test.csv", function(data){
var max = d3.max(data, function(d) { return +d.field_goal_attempts;} );
var yScale = d3.scale.linear().domain([0,max]);
...
}
If you want to find both max and min then I suggest using d3.extent(...) which should also accept an accessor function and will return an array of length 2 with the min and max values.
1) The yScale can stay outside of the d3.csv()
function as long as you update the domain inside of the function when having computed the max. For example you could do the following inside of d3.csv()
:
yScale.domain([0, my_max])
2) To compute the max, here is the method I usually use:
//Create list containing only field_goal_attempts
field_goal_attempts_list = data.forEach(function(d){return d.field_goal_attempts})
//Compute max using d3.max() function
field_goal_attempts_max = d3.max(field_goal_attempts_list)
It is true that passing such function to d3.max()
would be great but as far as I know it is not. The advantage of first computing the list and then computing the max is that you do less computation if you want to compute the min, the mean or anything else.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With