Stacked bar chart with negative JSON data - javascript

I am trying to implement stacked bar chart.
My data source is JSON array.
Data might be negative or positive.
I am referencing this link
http://bl.ocks.org/ZJONSSON/2975320
But the problem is the data used here like matrix type.
like :
var data = [[{y:3},{y:6},{y:-3}],
[{y:4},{y:-2},{y:-9}],
[{y:10},{y:-3},{y:4}]
]
I have same data but in JSON array like :
var data = [{x:"abc", y1:"3", y2:"4", y3:"10"},
{x:"abc2", y1:"6", y2:"-2", y3:"-3" },
{x:"abc3", y1:"-3", y2:"-9", y3:"4"}
]
Now my question is how I can implement this graph with JSON formatted data.

In the example you linked, the original data is grouped by band type. Your data is grouped by set - that is, in the original each color band is grouped in the data array. In your data, each stack of bands is a group of objects in the data array.
If you want to reuse the original code, we need to translate the data (90 degrees) like so:
var initialData = [{x:"abc", y1:"3", y2:"4", y3:"10"},
{x:"abc2", y1:"6", y2:"-2", y3:"-3" },
{x:"abc3", y1:"-3", y2:"-9", y3:"4"}]
var data = ["y1","y2","y3"].map(
function(v){
return initialData.map(function(d){
return {y: +d[v]};
});
});
Then, most of the original code can be used as-is.
Another part which you can adapt is the domain for the x-scale
x = d3.scale.ordinal()
.domain(['abc','abc2','abc3'])
.rangeRoundBands([margin,w-margin], .1)
The group names are hard coded, but you have them in your objects as "x".
Instead, we can automatically use the x value of each object as the label for each set:
x = d3.scale.ordinal()
.domain(initialData.map(function(d){return d.x}))
.rangeRoundBands([margin,w-margin], .1)
Putting it all together, with some extra values: http://jsfiddle.net/fLMAZ/1/
The other option is to rewrite the code to bind the data as-is, but you will need to understand how the stacked bar chart is built and then adapt it to your original JSON.

You have a couple of options:
Is to provide the data from the server side to make it look like the JSON structure that graph likes.
You can parse through your JSON on the client side and make a new JSON
You can modify the graph chart such that it will work with your JSON

Related

How to use scatter chart with complex data?

I trying to implement scatter chart by example.
In example we can see creating dimension:
runDimension = ndx.dimension(function(d) {return [+d.Expt, +d.Run]; });
Example's data:
Expt Run Speed
1 1 850
1 2 740
1 3 900
I want to use same chart, but I have my data in next format:
[
{
"Timestamp":"2016-12-15T17:29:53Z",
"idgame":"euro",
"users":{
"Jo": {
"energy":200,
"jump_height":0.5
},
"Bob": {
"energy":220,
"jump_height":0.35
}
}
},
{
"Timestamp":"2016-12-15T17:29:55Z",
"idgame":"euro",
"users":{
"Jo": {
"energy":120,
"jump_height":0.15
},
"Bob": {
"energy":240,
"jump_height":0.75
}
}
}
]
I need to build next chart, where x-axis is timestamp and y-axis is jump_height:
My data is allready in crossfilter, so I can't change it.
How can I create good dimension with current format?
I'm still not convinced this is worth the effort, versus biting the bullet and flattening your data and fixing up the other charts. If your data isn't flat you will be fighting crossfilter and dc.js every step of the way.
That said, as usual, it's possible!
We can't use the series chart, because that requires all the data to be present in one group. But since you want to produce multiple symbols from each row of data, an ordinary crossfilter group can't produce the data you need.
Maybe we could use a fake group, but that would be complicated. Instead, let's produce a dimension and group for each user, and then sew them together using a composite chart.
First, we need to parse those timestamps:
data.forEach(function(d) {
d.Timestamp = new Date(d.Timestamp);
});
Next, we'll retrieve a list of all users, by pulling the user keys from each event (timestamp), concatenating them, and then using a d3.set to unique them:
// retrieve all users from all events
var users = data.reduce(function(p, event) {
return p.concat(Object.keys(event.users));
}, []);
users = d3.set(users).values();
In the rest of the code, we'll assume there are the same users for each event. It's possible for them to be different, but it adds extra complexity, and this answer is complicated enough. Just ping me me if you need that feature!
We'll create the chart, crossfilter, and a scale which will assign symbols to users:
var chart = dc.compositeChart("#test");
var ndx = crossfilter(data);
var symbolScale = d3.scale.ordinal().range(d3.svg.symbolTypes);
Now we can create the composite chart. (We'll add the scatter subcharts in the next step.)
chart
.width(768)
.height(480)
.x(d3.time.scale())
.xUnits(d3.time.seconds)
.elasticX(true)
.elasticY(true)
.brushOn(false)
.clipPadding(10)
.shareTitle(false) // allow default scatter title to work
.shareColors(true) // but use different colors for subcharts
.legend(dc.legend().x(350).y(350).itemHeight(13)
.gap(5).horizontal(1).legendWidth(140).itemWidth(70));
We set up the X axis with a time scale, with a resolution of seconds. Both axes have elastic. We need to share colors so that each subchart will be assigned its own color. (The legend is perhaps overspecified - I copied this from another example.)
Finally we get to the meat of it. For each user, we'll create a subchart, and we'll tell the composite chart to compose all of them:
chart.compose(users.map(function(user) {
var userDimension = ndx.dimension(function(d) {
return [d.Timestamp, d.users[user].jump_height];
})
var jumpGroup = userDimension.group();
console.log(user, jumpGroup.all());
var scatter = dc.scatterPlot(chart)
.symbol(symbolScale(user))
.dimension(userDimension)
.group(jumpGroup)
.colorAccessor(function() { return user; })
.symbolSize(8)
.highlightedSize(10);
return scatter;
}))
We're creating a new dimension for each chart. This is because the dc.js scatter plot expects the keys to include both X and Y coordinates, and we can only access the Y coordinate (jump_height) once we know the user. Once we get past that, the group is simple.
The chart will assign the symbol and color based on the user key. These both work the same; an ordinal scale will assign a new value from the range for each new value it encounters in the domain. The only difference is that we're using the default color scale, whereas we had to specify our own symbol scale.
Here's a fiddle: https://jsfiddle.net/gordonwoodhull/3m4mv3xf/19/

Pull specific keys with values to use in bar chart

My data looks like this
var data = [
{'date':'1/1/17', 'cars':2.0, 'trucks':3.0, 'suvs':4.0, 'bikes':0,'skates':0}
{'date':'2/1/17', 'cars':4.0, 'trucks':7.0, 'suvs':4.0, 'bikes':1.0,'skates':0.0}
{'date':'3/1/17', 'cars':0.0, 'trucks':3.0, 'suvs':5.0, 'bikes':0.0,'skates':4.0}
I'm trying to plot this in a bar chart using dc or d3, with my x axis being vehicle (bike, truck,skates) and my y axis being the count.
Is there a smart way to do this?
This link is what I'm basing my project
dc example
but I think their data formatted differently (i.e.)
var data = [
{'name':'apple', 'count':2.0},
{'name':'bannana', 'count':4.0},...]
So I don't know if this is even possible

Javascript D3 How to access and manipulate dataset from CSV

I am struggling with D3. I have a dataset that I am pulling into D3, and populating a bar chart. The problem is there are too many bars! I want to only display the top 10 values.
My csv has two values, the key (column header) is "Name" and the value is "NumberOfTickets". I want to show only 10 names that have the most tickets. I assume i need to sort and splice my dataset, but I have tried everything and cant get it to work. It seems most tutorials are geared towards simple arrays and not a dataset that comes from a CSV with key value pairs. Any help would be appreciated. Here is my dataset portion of the D3 code. I assume this is where I need to manipulate the dataset:
var report = data.forEach(function(d){
d.Name= d.Name;
d.NumberOfTickets= +d.NumberOfTickets;
});
Try this:
var report = data.sort(function(a, b) {
return d3.descending(+a.NumberOfTickets, +b.NumberOfTickets);
}).slice( 0, 10);
If you want the names that get less tickets, just change for "ascending". If you want to change your slice, remember that the start number is inclusive, but the ending number is not.

Plot within a tooltip in d3.js

I would like to create a d3-based plot which graphs a plot within a tooltip. Unfortunately, I haven't found any examples on the web. Here is a sample JSON file.
[{"x":[0.4],
"y":[0.2],
"scatter.x":[0.54,0.9297,0.6024,-1.9224,2.2819],
"scatter.y":[0.4139,1.1298,-0.1119,2.3624,-1.1947]},
{"x":[0.1],
"y":[0.9],
"scatter.x":[-0.8566,-0.5806,-0.9326,0.8329,-0.5792],
"scatter.y":[-0.5462,-0.7054,1.0264,-3.4874,-1.0431]}]
The idea is to have a scatter plot for (x,y) coordinates first. However, when one mouses over a point, a different scatter plot within a tooltip appears based on [scatter.x, scatter.y] coordinates for that respective point.
I can do the scatter plots separately but have been struggling to put them together. Could anyone shed some light on this and/or provide a minimal example?
This was too long for a comment but I'm not certain if it's the answer you were looking for. One of the issues you might find is that your nested data is formatted differently-- one uses JSON objects with x and y, while the other uses two arrays of points.
My solution to this would be to create an extensible function:
function makeScatterPlot(elem, width, height, data, fill)
elem, width, height, and data are the core parameters: which element to attach the chart to, the size of the chart, and the data for the chart (in the JSON object format).
This function would generate all necessary items for the chart and add the chart to the provided element.
Then you want to bind to mouseover of your main chart, and in that function you'll have to do a bit of data modification to re-organize the two arrays into the JSON object structure.
function mainMouseover(d){
var newData = [];
for (var i = 0; i < d["scatter.x"].length; i++){
var t = {x: [0], y: [0]};
t.x[0] = d["scatter.x"][i];
t.y[0] = d["scatter.y"][i];
newData.push(t);
}
var newG = mainG.append("g").attr("transform", "translate(200,200)");
makeScatterPlot(newG, 100,100, newData, "red");
}
Of course, you would modify the translate to match wherever you want your tooltip to be.
Putting this all together you get the following (very crude) fiddle. Hover over either of the black dots to see the sub-chart. Obviously this needs quite a bit of work to be a solid example (i.e. remove the sub-chart on mouseout), but hopefully it will set you in the right direction.
If the tooltip chart is significantly different styling-wise compared to your main chart it may not be the best idea to use an extensible function, and you could just create another custom function instead.

DimpleJS - Limit the number of category axis values to be displayed in chart

For preparing graphs from data that exists in MySQL tables, I am using DimpleJS framework. I am able to plot graphs, everything works. One question though -
In a simple bar chart, with category values on X axis and measure values on Y axis, is there a way to limit the number of X axis categories being displayed? Example, let's say this is my data set: [(A,1), (B,2), (C,1), (D,5), (E,4)]
So in my dataset, there are 5 categories (X axis - A, B,C,D,E) and corresponding measures that I will be displaying in Y axis. Question is, I just want to display only 3 of the measures - let's say only first three, in this case (A,1), (B,2) and (C,1), although my dataset has two more (D,5) and (E,4).
Is there any way to restrict it in JS/ DimpleJS? I have limited control on the dataset that is coming in.
Thanks.
Use dimple.filterData after you receive the dataset but before you provide the data to dimple. This does not mutate the data so won't affect any other operations. I'm not sure what your actual category field is but it should look similar to this :
var chartData = dimple.filterData(originalDataset, 'category', ["A", "B", "C"]);
var chart = new dimple.chart(svg, chartData);
Otherwise there is not a provided way to restrict a category axis from showing values present in the data.

Categories