Reputation: 120
I've been teaching myself d3 overnight and can't seem to figure out this one issue I am having. I am dynamically feeding the d3.max()
method an array of numbers (I have tried parsing them with parseInt()
/parseFloat()
as well as not parsing them) through an HTML <select>
element. I am using the console to check the values as my visualizations are becoming skewed. However, sometimes it does return the max value, and sometimes it just doesn't.
var localityElectricityConsumption = localities[localityName].totalElectricityConsumption;
maxConsumption = d3.max(localityElectricityConsumption);
r = d3.scale.linear().domain([0, maxConsumption]).range([120, 0]);
console.log("array being fed to d3.max: " + localityElectricityConsumption);
console.log("what d3.max() is returning: " + d3.max(localityElectricityConsumption));
console.log("what parseInt(d3.max()) is returning: " + d3.max(localityElectricityConsumption));
You can see the live visualization and check the console here. Try using the top-most graph to switch from the North American locality to the Mexico locality. d3.max()
returns the max value for North America, but not Mexico, and therefore doesn't graph the data correctly for Mexico. I am officially stumped. Any help would be appreciated.
EDIT:
Here is the code that is used to create localities[localityName].totalElectricityConsumption
:
d3.csv("data/" + dataset, function (data) {
for (var i = 0; i < data.length; i++) {
var record = data[i];
if (dataset === "total_electricity_consumption.csv") {
currentDataset = listOfDatasets[0].name;
record.totalElectricityConsumption = [];
// loop through all years, from 1980 to 2012
for (var year = 1980; year <= 2012; year++) {
var value = record[year];
// deal with missing data points
if (value === '--') {
value = 0;
}
else if (value === 'NA') {
value = 0;
}
else if (value === '(s)') {
value = 0;
}
else if (value === 'W') {
value = 0;
}
// add record of current total electricity consumption
record.totalElectricityConsumption.push(value);
}
}
// create a list of country names
localities[record.Locality] = record;
listOfLocalities.push(record.Locality);
}
}
Sorry, formatting is not perfect as I had to take some stuff out to make the code more readable for Stack Overflow.
Upvotes: 2
Views: 2511
Reputation: 102198
As expected, d3.max()
is indeed returning the maximum value... however, it is returning the maximum value among strings, not among numbers.
The explanation is that, by default, d3.csv()
will load all the values as strings, even if they are numbers. Therefore, when you do:
var value = record[year];
value
is a string, not a number. And in JavaScript the maximum for an array of strings is different from the maximum for an array of numbers. For instance, using numbers:
var myArray = [1, 65, 9, 32, 42];
console.log(d3.max(myArray));
<script src="https://d3js.org/d3.v4.min.js"></script>
That's the expected value. But look what happens if we use strings:
var myArray = ["1", "65", "9", "32", "42"];
console.log(d3.max(myArray));
<script src="https://d3js.org/d3.v4.min.js"></script>
Solution: change your values to numbers:
var value = +record[year];
Upvotes: 9