Multiple y-axis values against one single x-axis point - javascript

I have implemented AMCharts JS library in one of my web apps and am having an issue. Right now i need to add multiple y-axis values to one single x-axis point (which is actually a date). I have 5 values 5,1,5,4,1,3 which contain same x-axis point (same date) but when i observe the graph sometimes 4 is missing while sometimes 5 as shown in the image. Am i really doing something wrong? This is the form of data
{date: "2016-03-29", value: 5}
{date: "2016-03-29", value: 1}
{date: "2016-03-29", value: 5}
{date: "2016-03-29", value: 4}
{date: "2016-03-29", value: 1}
{date: "2016-03-29", value: 3}
{date: "2016-10-20", value: 0}
{date: "2016-10-20", value: 0}
{date: "2016-10-20", value: 0}

There are a couple of issues with your setup.
First, your data is structured incorrectly for a chart with parseDates enabled. You can't have multiple elements of the same date. AmCharts requires that you group your data points if they share the same date/category. This is by design and every single example on the website shows this, so all of your 2016-03-29 and 2016-10-20 points can be reduced into two objects. I'm presuming that those multiple values correspond to different graph objects, so you need unique value fields for each, i.e.
[{
date: "2016-03-29",
value1: 5,
value2: 1,
value3: 5,
value4: 4,
value5: 1,
value6: 3
}, {
date: "2016-10-20"
value1: 0,
value2: 0,
value3: 0
}]
And then you have 6 graph objects with valueFields set to value1 through value6 to accommodate for those points. Again, I'm assuming that you have multiple graphs given your dataset.
Edit
Your comment indicates that this is not the case and they all belong to one graph. You still need to restructure your data and give unique timestamps since you can't have multiple entries with the same timestamp for a parseDates-enabled chart. If those values came in at different times, then provide that information. For example, assuming your data is hourly:
{date: "2016-03-29 01:00", value: 5}
{date: "2016-03-29 02:00", value: 1}
{date: "2016-03-29 03:00", value: 5}
{date: "2016-03-29 04:00", value: 4}
{date: "2016-03-29 05:00", value: 1}
{date: "2016-03-29 06:00", value: 3}
{date: "2016-10-20 01:00", value: 0}
{date: "2016-10-20 02:00", value: 0}
{date: "2016-10-20 03:00", value: 0}
This will work but you have to set your dataDateFormat to match the timestamp (in this case "YYYY-MM-DD JJ:NN") and adjust your minPeriod to accommodate for the smallest interval in between your points (for this example: "hh").
If you don't parse dates, then you can keep your setup, but the chart will look weird with multiple 2016-03-29 entries. Those are your only options.
As for displaying multiple value axes, a value axis needs to be associated with a graph. If you need multiple value axes, then you need multiple graphs. Each graph's valueAxis property needs to be assigned to a valueAxis object or valueAxis id. You can't assign multiple value axes to one graph object. You can see how this works in this example.
If you only have one graph and need to display a second value axis, create a duplicate graph instance and disable visual aspects of it, like so:
valueAxes: [{
"position": "left",
"id": "v1"
}, {
"position": "right",
"id": "v2"
}],
graphs: [{
//initial graph
type: "line",
bullet: "round",
valueField: "value"
}, {
//invisible duplicate graph
//for second axis
lineAlpha: 0,
showBalloons: false,
visibleInLegend: false,
valueAxis: "v2",
valueField: "value"
}],
Demo

Related

Javascript - How to access object

I have an object with store in this variable report[sales] which contain information such as all, amount, month as an object.
When i tried to console log the following console.log(report[sales]), i received the result of {All: 1, amount: 855, month: 2}.
But when i want to access the value for All which I tried the following report[sales].All the result is undefined and I also tried report[sales]["All"].
** Edit **
Result of console.log(report)
{Feb: {All: 1, amount: 855, month: 2, …}}
Result of console.log(report[sales])
{All: 1, amount: 855, month: 2, …}
I want to access value of All
Try this
const report = {
sales: {All: 1, amount: 855, month: 2}
}
console.log(report.sales.All);
Just try console.log(report.sales.All); it will work
Thanks for adding the text to your question. I have no idea where you got sales from based on the info you provided, but below is a couple examples on how to log out the value of All. Another thing, you stated that report is an array, however it actually is an object based on your console.log in your question.
let report = {Feb: {All: 1, amount: 855, month: 2}, March: {All: 2, amount: 855, month: 2}}
// Just log out the Feb.All value
console.log(report.Feb.All);
// A for in loop is an easy way to loop over objects
for(let i in report) {
// This will log out all the All values in the object.
// Just swap out All with amount or month to print the other values.
console.log('All = ' + report[i].All);
}

Programmatically highlighting DyGraph time series

I’m putting together an web-app that plots time series of weather data for the current year and the past 10 years on one dygraph. I want the time series for the current year (2015 at this time) to be highlighted relative to the past years, so I’m trying to increase the strokewidth for the current year from a default of 2 to 5. My problem is that I’m having trouble getting this to work programatically. The daily data for each year is in native array format, so the time series are identified by the contents of the array Yr0Labels:
["Date", "2005", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015"]
Next January 1 the Yr0Labels will programmatically change to:
["Date", "2006", "2007", "2008", "2009", "2010", "2011", "2012", "2013", "2014", "2015",”2016”]
In the dygraph options parameter I set default strokeWidth to 2 and the strokeWidth for 2015 to 5. Because I want the current calendar year data to be highlighted properly after Jan. 1 , I’ve tried identifying the series to be highlighted by the contents of yr0Labels[11],
{
……
strokeWidth: 2,
labels: yr0Labels,
series: { yr0Labels[11] : { strokeWidth: 5} },
……..
}
This produced a syntax error - SyntaxError: missing : after property id
Suspecting that dygraph didn’t want to see array syntax in the series identifier, I tried to identify the series via a string variable “cyear”,
cyear = yr0Labels[11];
{…strokeWidth: 2,
labels: yr0Labels,
series: { cyear : { strokeWidth: 5} },
…….}
This didn’t produce an error, but also didn’t highlight the series.
The only way I’ve been able to make this work is to directly enter the current year value as the series identifier,
{…strokeWidth: 2,
labels: yr0Labels,
series : { ‘2015’ : { strokeWidth: 5} },
…….}
This worked, but I’d have to edit the dygraph option parameter every Jan. 1 to make data for the current calendar year plot properly.
How I can make this highlighting work programmatically?
The issue is with how you're using keys in JavaScript object literals.
This:
{ foo: 'bar' }
is the same as:
{ 'foo': 'bar' }
even if there's a variable in scope called foo. To achieve the result you want, you need to do fill out your objects using something like:
var foo = 'blah';
var o = {};
o[foo] = 'bar';

Multi Level mappings in Parent/Child hierarchy in D3 Possible?

I've a flat file which is of format
"id":1,"depends_on":2
"id":1,"depends_on":4
"id":1,"depends_on":5
"id":2,"depends_on":3
"id":4,"depends_on":5
Normally if I don't have
"id":1,"depends_on":5
I can plot the D3 Layout as follows
When I include "id":1,"depends_on":5
Graph that's being plot will be
Ideally I should have a line between 1 & 5 too, along with other mappings.
1)How can I achieve this?
2)How should the data-structure should be?
Does it really need to have duplicate entries (objects) in various parts of main data-structure ( to obtain in the format D3 needed (parent,children[])
Using d3.layout.force produces
Check out this example, which uses d3.layout.force().
A force layout's data structure involves 2 arrays:
an array of nodes
[{id: 1}, {id: 2}, {id: 3}, {id: 4}]`
and array of links
[
{ source: {id: 1}, target: {id: 2} },
{ source: {id: 1}, target: {id: 3} },
{ source: {id: 2}, target: {id: 4} }
]
The objects used in the nodes array and links array should be the same objects. I.e, in the example above, nodes[0] == links.source[0] should be true.

Updating a choropleth map with a dropdown button

First, please excuse my poor english.
I'm working on a project with a grid-map and an external csv.
The grid-map is not composed of rectangles or hexagons but only with the centroid of any kind of symbol that will be use at the end.
So I have a Topojson file with centroids "ID" and centroids "Coordinates".
The external CSV is composed of several columns, the first one with the same centroids "ID" and the other one with value for different year.
"ID","C2001","C2002","C2003","C2004","C2005","C2006","C2007","C2008","C2009","C2010","C2000"
6050,"-5.55753","-5.55914","-5.75444","-5.76307","-5.81660","-5.99361","-6.02150","-6.15979","-5.73530","-6.30509","-5.52990"
6051,"-5.55753","-5.55914","-5.75444","-5.76307","-5.81660","-5.99361","-6.02150","-6.15979","-5.73530","-6.30509","-5.52990"
Here is my code
var width = 960,
height = 600;
var options = [
{date: "2000", selected: "+d.C2000"},
{date: "2001", selected: "+d.C2001"},
{date: "2002", selected: "+d.C2002"},
{date: "2003", selected: "+d.C2003"},
{date: "2004", selected: "+d.C2004"},
{date: "2005", selected: "+d.C2005"},
{date: "2006", selected: "+d.C2006"},
{date: "2007", selected: "+d.C2007"},
{date: "2008", selected: "+d.C2008"},
{date: "2009", selected: "+d.C2009"},
{date: "2010", selected: "+d.C2010"},
];
var color = d3.scale.threshold()
.domain([-1985, -1400, -1000, -700, -300, -100, -25, -0])
.range(["#7f0000", "#b30000", "#d7301f", "#ef6548", "#fc8d59", "#fdbb84", "#fdd49e", "#fee8c8", "#fff7ec"]);
var path = d3.geo.path()
.projection(null)
.pointRadius(1.5);
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
queue()
.defer(d3.json, "CO2_light.json")
.defer(d3.csv, "tdd_CO2_emissions.csv")
.await(ready);
function ready(error, centroid, CO2) {
var rateById = {};
console.log(rateById); //To
//CO2.forEach(function(d) { rateById[+d.ID] = +d.C2000; }); WORKING FINE = value in rateById
CO2.forEach(function(d) { rateById[+d.ID] = options[0].selected; }); //NOT WORKING = inside rateById "+d.C2000" instead the value
svg.selectAll("path")
.data(topojson.feature(centroid, centroid.objects.CENTROID).features)
.enter().append("path")
.attr("class", "centerGrid")
.attr("d", path)
.style("fill", function(d) { return color(rateById[+d.properties.ID]); });
d3.select(".loading").remove();
For the moment I leave the button for my next problem and I'm focus on this two line below
//CO2.forEach(function(d) { rateById[+d.ID] = +d.C2000; }); WORKING FINE = value in rateById
CO2.forEach(function(d) { rateById[+d.ID] = options[0].selected; }); //NOT WORKING = inside rateById "+d.C2000" instead the value
If I use the first line I get a nice grid-map (see image) but if I'm trying to access at value of a specific year from the options array with the second line and do console.log(rateById); I get this
Object
6050: "+d.C2000"
6051: "+d.C2000"
6712: "+d.C2000"
Instead of this
Object
6050: -6.30509
6051: -6.30509
6712: -7.0441
Fixed here: http://jsfiddle.net/z7sLdyu2/2/
2 changes to do in your code:
First, your options select should not contain javascript code to be executed (+d.), but only the year values:
var options = [
{date: "2000", selected: "C2000"},
{date: "2001", selected: "C2001"},
{date: "2002", selected: "C2002"},
{date: "2003", selected: "C2003"},
{date: "2004", selected: "C2004"},
{date: "2005", selected: "C2005"},
{date: "2006", selected: "C2006"},
{date: "2007", selected: "C2007"},
{date: "2008", selected: "C2008"},
{date: "2009", selected: "C2009"},
{date: "2010", selected: "C2010"}
];
Then in the loop, assign the rateById value by accessing the data d property for the selected year like this:
rateById[+d.ID] = +d[options[0].selected];
P.S.: I had to remove part of your code in your jsfiddle, as the centroids json was not found in your version of the jsfiddle, leading to errors not related to the problem of this question.

JQuery $.extend() recursivity peculiarity

I want to extend an object in a specific position in an array, without having to send the whole array again.
Example:
You start out with the array like this:
sensors = [{value: 10}, {value: 20}];
Now say I want to change the value of the second sensor, I can do this in jQuery:
newSensorValue = {1: {value:30}};
$.extend(true, sensors, newSensorValue);
// sensors = [{value: 10}, {value: 30}];
However, if the array is not directly the object that is merged, this does not work:
node = {x: 10, y: 10, node_id: 1, sensors: [
{sensor_id: 1, value: 10},
{sensor_id: 2, value: 20}
]};
newNodeData = {sensors: {
1: {value:30}
}};
$.extend(true, node, newNodeData);
// node = {x: 10, y: 10, node_id: 1, sensors: {
// 1: {value:30}
// }};
Why does $.extend() suddenly behave differently if the array is nested in an object?
My own solution would be to create an array of empty objects, only giving the object that I want to change the "value" attribute, like:
newNodeData = {sensors: [
{}, {value: 30}
]};
Since this seems rather ugly, is there a better way to do this?
I would prefer to keep the sensors attribute an array, since I like to use forEach to go through each sensor quickly.
EDIT: forgot to mention that if I do
$.extend(true, node.sensors, newNodeData.sensors);
It works the same as in the first example (i.e. it works)
You could leave the element empty when you don't want to change it.
node = {x: 10, y: 10, node_id: 1, sensors: [
{sensor_id: 1, value: 10},
{sensor_id: 2, value: 20}
]};
newNodeData = {sensors: [,{value:30}]};
$.extend(true, node, newNodeData);

Categories