Basic d3js max returning multiple values - javascript

I'm trying to get just one value from d3's max function but it's returning an entire array. Here is an example:
var data = {
"Jim" : [
{
"Value" : [10,11,12]
}
]
}
var myMax = d3.max(data.Jim, function(d){
var maxVal = d["Value"];
return maxVal;
})
console.log(myMax + "max")
It returns 10,11,12max. It should return 12.

you're trying to find the maximum of the array data.Jim which only has one element = {"Value" : [10,11,12]} which d3 promptly returns as the maximum using your given accessor function. Try changing your code to the following:
var myMax = d3.max(data.Jim, function(d){
var maxVal = d3.max(d["Value"]);
return maxVal;
})

Related

Function not returning the volume value

i was wondering why this function its not working as far as my understanding goes(newbie) when invoking i should have the value[0] and [1] in order to get the result that i am looking for but i have tried in the browser and in console.log and i am not getting the [1] return value as expected.
function getSize(width, height, depth) {
var area = width * height;
var volume = width * height * depth;
var sizes = [area, volume];
alert(area);
}
var areaOne = getSize(3, 2, 1)[0];
var volumeOne = getSize(2, 1, 5)[1];
Here you are missing return.
A function should always return value.
function getSize(width,height,depth){
var area =width * height;
var volume=width*height*depth;
var sizes=[area,volume];
//alert(area);
return area;
}
var areaOne=getSize(3,2,1)[0];
var volumeOne=getSize(2,1,5)[1];
console.log(volumeOne)
You should return the value form you function in order to retrieve the values.
function getSize(width,height,depth){
var area =width * height;
var volume=width*height*depth;
var sizes=[area,volume];
return [volume, area]; // you should reuren the value in order to get it
}
var areaOne=getSize(3,2,1)[0];
var volumeOne=getSize(2,1,5)[1];
console.log(areaOne, volumeOne);
Your function doesn't have a return parameter, in order to assign functions output (in this case sizes[] array) your function needs to return that value, just add return sizes; at the end of your function definition.

Finding maximum of the selected column in loaded csv data in Javascript

function myFunction() {
dd = document.getElementsByClassName("addin");
ds = document.getElementsByClassName("slidfi");
var arr = [];
for(var i = 0;i< dd.length;i++){
var obj = {};
obj["check"] = dd[i].checked;
obj["value"] = ds[i].value;
obj["headers"] = dd[i].value;
arr.push(obj)
}
return arr;
}
status variable in the below function have details of value and status[i]["header"] which is column value for corresponding header and I want to divide each of the value with the max value in the whole column. It should be basically something like this -
temp.push((d[status[i]["headers"]]/Math.max(temp)) * status[i]["value"])
but I am not able to get max for entire column.
Here is the current code but also want to take max and divide by each value to normalize it then multiply by status[i]["value"].
function UpdatedData() {
var status = myFunction();
d3.csv('cars.csv', function(error, data) {
data.forEach(function(d){
var temp=[];
for(var i=0;i<status.length;i++){
if (status[i]["check"]){
temp.push(d[status[i]["headers"]] * status[i]["value"])
}
}
});
});
}
status is an array with this format.
0 {check: false, value: "0.5", headers: "W"}
1 {check: false, value: "0.5", headers: "X"}
2 {check: true, value: "0.5", headers: "Y"}
3 {check: true, value: "0.5", headers: "Z"}
So last two are checked,so in this case temp will be an array of dim 2. One will be correspond to header Y and other to corresponding header Z. I want the max for the all column value corresponding to Y and Z but not the max within Y and Z
You need to calculate the max of the entire column in a loop first, doing something like
maxTemp = 0;
for(var i=0;i<status.length;i++){
if (status[i]["check"]){
if(maxTemp < d[status[i]["headers"]])
maxTemp = d[status[i]["headers"]];
}
}
Then divide the using the maxTemp in another loop
for(var i=0;i<status.length;i++){
temp.push((d[status[i]["headers"]]/maxTemp) * status[i]["value"])
}
**Pseudo Code **
maxTemp = 0;
data.forEach(function(d){
//some code
if(maxTemp < d[status[i]["headers"]])
maxTemp = d[status[i]["headers"]];
}
})
data.forEach(function(d){
//some code
temp.push(value /maxTemp)
})
As your question's title is a bit different from your question's text, I'll address the question's title only. I hope that it suits you.
You can find the maximum of any column using the D3 method d3.max, which:
Returns the maximum value in the given array using natural order. If the array is empty, returns undefined. An optional accessor function may be specified, which is equivalent to calling array.map(accessor) before computing the maximum value.
So, given this bogus CSV:
foo, bar, baz
12, 14, 65
26, 75, 39
67, 11, 93
19, 42, 17
We can find the maximum of the foo column with:
var maxFoo = d3.max(data, function(d){ return d.foo});
For finding the maximum of two or more columns, we can simply create an array with the individual maximum values:
var maxFooBar1 = d3.max([maxFoo, maxBar]);
Or, alternatively, we can find the maximum in each object:
var maxFooBar2 = d3.max(data, function(d){ return d3.max([d.foo, d.bar])});
Here is a demo (I'm using a pre element to simulate the CSV):
var data = d3.csvParse(d3.select("#csv").text());
data.forEach(function(d) {
d.foo = +d.foo;
d.bar = +d.bar;
d.baz = +d.baz;
})
var maxFoo = d3.max(data, function(d) {
return d.foo
});
var maxBar = d3.max(data, function(d) {
return d.bar
});
var maxFooBar1 = d3.max([maxFoo, maxBar]);
var maxFooBar2 = d3.max(data, function(d) {
return d3.max([d.foo, d.bar])
});
console.log("The max of foo is: " + maxFoo)
console.log("The max of foo and bar is (method 1): " + maxFooBar1)
console.log("The max of foo and bar is (method 2): " + maxFooBar2)
pre {
display: none;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<pre id="csv">foo,bar,baz
12,14,65
26,75,39
67,11,93
19,42,17</pre>

How to create a stacked bar chart using dc.js?

I'd like to create a stacked bar chart using DC.JS.
I've tried to utilize the documentation from DC.JS (graph,source code) to no avail - Below is my attempt (here is my attempt in jsfiddle) and my most recent attempt in CodePen.
I'd like the 'Name' as the X axis and 'Type' as the stacks.
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
<script src="https://rawgithub.com/NickQiZhu/dc.js/master/web/js/crossfilter.js"></script>
<script src="https://cdnjs.site44.com/dc2.js"></script>
<div id="chart"></div>
Javascript
var data = [ {"Name":"Abby","Type":"Apple"}, {"Name":"Abby","Type":"Banana"}, {"Name":"Bob","Type":"Apple"} ]
data.forEach(function(x) {
x.Speed = +x.Type;
});
var ndx = crossfilter(data)
var xdim = ndx.dimension(function (d) {return d.Name;});
function root_function(dim,stack_name) {
return dim.group().reduce(
function(p, v) {
p[v[stack_name]] = (p[v[stack_name]] || 0) + v.Speed;
return p;},
function(p, v) {
p[v[stack_name]] = (p[v[stack_name]] || 0) - v.Speed;
return p;},
function() {
return {};
});}
var ydim = root_function(xdim,'Type')
function sel_stack(i) {
return function(d) {
return d.value[i];
};}
var chart = dc.barChart("#chart");
chart
.x(d3.scale.ordinal().domain(xdim))
.dimension(xdim)
.group(ydim, "1", sel_stack('1'))
.xUnits(dc.units.ordinal);
for(var i = 2; i<6; ++i)
chart.stack(ydim, ''+i, sel_stack(i));
chart.render();
I've been fiddling with this for some time and I have some additional findings:
When I replace the data array with the following it works
data = [ {"Name":"Abby","Type":"1"}, {"Name":"Abby","Type":"2"}, {"Name":"Bob","Type":"1"} ]
But it only works when I swapped out dc 1.7.5 (https://cdnjs.cloudflare.com/ajax/libs/dc/1.7.5/dc.min.js) with dc 2.1.0-dev (https://github.com/dc-js/dc.js/blob/develop/web/js/dc.js)
However when I replace the data array with the following it doesn't work:
data = [ {"Name":"Abby","Type":"3"}, {"Name":"Abby","Type":"4"}, {"Name":"Bob","Type":"2"} ]
I believe the root issue lies in the root_function.
v.Speed is always NaN in your current example. Because +x.Type attempts to convert a string like "Apple" into a number and fails. If you just want to count, then add or subtract 1 in your reducer, rather than v.Speed. Then you need to update your sel_stack code and chart code to handle this change, of course.
Here's a working example for the 2 types in your data. You'll have to update it to handle arbitrary numbers of types, probably by building an array of all your types up front and then looping through it to add stacks to the chart: http://codepen.io/anon/pen/GjjyOv?editors=1010
var data = [ {"Name":"Abby","Type":"Apple"}, {"Name":"Abby","Type":"Banana"}, {"Name":"Bob","Type":"Apple"} ]
var ndx = crossfilter(data)
var xdim = ndx.dimension(function (d) {return d.Name;});
In the reducer, just add and subtract 1 to count:
var ydim = xdim.group().reduce(
function(p, v) {
p[v.Type] = (p[v.Type] || 0) + 1;
return p;},
function(p, v) {
p[v.Type] = (p[v.Type] || 0) - 1;
return p;},
function() {
return {};
});
sel_stack no longer takes a number, but a key:
function sel_stack(valueKey) {
return function(d) {
return d.value[valueKey];
};}
var chart = dc.barChart("#chart");
Here we hard-code the stack key, for the purpose of the example:
chart
.x(d3.scale.ordinal().domain(xdim))
.dimension(xdim)
.group(ydim, "Apple", sel_stack('Apple'))
.xUnits(dc.units.ordinal);
Again, the other hard-coded stack key. You'll need to recreate the loop after creating some sort of data structure that holds all of your stack values.
//for(var i = 2; i<6; ++i)
chart.stack(ydim, 'Banana', sel_stack('Banana'));
chart.render();

Manipulating JSON with LoDash

I've just started working with Lodash, and am trying to average out any value (at the lowest level) that's an array. No matter what I try, the original JSON persists.
Do I need to build a brand new object and push everything into it? Why can't I simply manipulate it like I would an array?
function averageIt(mtcs) {
function jsonAvg(dataSet) {
function avg(elmt) {
var sum = 0;
for( var i = 0; elmt[i]; i++ ){
sum += parseInt( elmt[i], 10 );
}
return Math.round(sum/elmt.length * 100) / 100;
}
_.forEach(dataSet.json, function(day) {
_.mapValues(day, function(n) {
return _.isArray(n) ? avg(n) : n;
});
});
console.log("JSON Averaged:", dataSet.json);
return dataSet;
}
_.forIn(mtcs.dataSets, function(set) {
set = jsonAvg(set);
});
console.log("Averaged Metrics:", mtcs);
return mtcs;
}
Regards
- - - Really Confused "Programmer"
If I understand it correctly, when you use _.mapValues is where the avg function is applied. But as you are using a map function, the result you set in the return is not stored anywhere, and the dataSet.json remains the same. You could do this:
_.each(dataSet.json, function(day, index) {
dataSet.json[index] = _.mapValues(day, function(n) {
return _.isArray(n) ? avg(n) : n;
});
});
Supposing that dataSet.json is an array. If it is an object, you should not apply an each to it, but do something like Object.keys(dataSet.json) to convert its properties to an array.

return biggest/highest object from jquery elements

Howdey!
Let's take a look at the following jQuery function:
$.fn.getMax = function() {
return this.height(Math.max.apply(this, $(this).map(function(i, e) {
return $(e).height();
}).get()));
};
It returns and sets the heighest height for all selectors. But what is, if you want to return the object (not the height) with the heighest value?
So if you call the function like this:
$(selector).getMax().css({backgroundColor: "indigo"});
...how the element with the heighest height gets the backgroundColor?
UPDATE
I've managed it now with $.makeArray, as Amareswar said it.
$.fn.getMax = function(prop) {
var max = $.makeArray($(this)).sort(function(a, b) {
return (parseInt($(b).css(prop), 10) || 1) - (parseInt($(a).css(prop), 10) || 1);
}).shift();
return $(max);
};
Cheers!
Try this:
$.fn.getMax = function() {
/* create array of heights*/
var heights = $(this).map(function(i, e) {
return $(e).height();
}).get();
/* get max height*/
var max = Math.max.apply(this, heights);
/* get index of max in array*/
var pos = $.inArray(max, heights)
/* return element with proper index*/
return this.eq(pos);
};
DEMO: http://jsfiddle.net/tTuE7/
EDIT : assumes you only want one element returned

Categories

Resources