I have an issue trying to color my bar chart dynamically based on a JSON response.
I know this has been asked a number of times before but none of the answers I've found or tried to work thorugh have got me any closer to a solution.
I've created a quick JSfiddle to show the issue.
I have a number of other charts which are all generated from different JSON strings so have cut this down a lot to try and isolate the issue. I don't have the same problem with the other charts as the number of entries in the Label array in consistent with the number of colours. The offending piece of code is this;
DT_Labels.forEach(function(DT_LABELS, x) {
data.datasets.push({
label: DT_LABELS,
backgroundColor: backgroundColor[x],
data: JSON.parse(DT_Values[x]).map(Number)
});
});
DT_Labels only contains a single entry as the chart is a summarised list - In theory, this would work if I counted the number of DT_Values but if I do that, I can't get the correct data in the chart.
Any ideas how I can reformat this to generate the colours counter based on the number of Values instead of Labels?
Change:
backgroundColor: backgroundColor[x],
to:
backgroundColor: backgroundColor,
Result:
Why does this work?
The backgroundColor property can be specified in a number of ways. Typically it's set to a string, e.g. #abcdef but it can also be set to an array. In this case Chart.js itself will pick the colour from the array based on the index of the data point it is drawing.
Related
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.
I've a chart generated from a JSON with a lot of data but in only one "x axe" serie. I'm not very clear but an example is better:
My chart
I would like to remove the blank between the columns and the right, in order to zoom in.
I read this post but the solution with
xAxis: {
min: 0,
}
doesn't work on my case (or maybe I'm doing it wrong..) because I have only one item on the X axe, the category "Students"
Here is my fiddle (names are random)
Sebastian's comment should answer the actual question, but I have to question using this set up in the first place.
The category itself serves no purpose if there's only one - the x axis title can fill that role, and eliminate any need for adjusting settings to behave normally.
A separate series for each student is definitely overkill, and results in 5 pages worth of legend entries, which can never hope to be associated with the actual student's column, as there are too many repeats of each color (and you're simply not going to come up with 73 distinctly identifiable colors, nor would it be useful to try...)
I would suggest a few things:
1) use a single series for all of the students. You gain nothing by using 73 different series
2) use each student's name as the category
3) forget about multiple colors - they add nothing useful, and there aren't enough of them even if they did
4) make it a horizontal bar chart instead of a column chart.
The result is a much more user-friendly display.
Example:
http://jsfiddle.net/jlbriggs/nx7z1387/
Also, if the goal is to show the values in a meaningful way, I would strongly consider sorting by value instead of by name. I realize there may be some argument for sorting it alphabetically, but it really shows the data in a much more understandable way when sorted by value.
Example:
http://jsfiddle.net/jlbriggs/nx7z1387/5/
FWIW
I'm using Highcharts for a project in which I have to display two series with about a thousand points each. The x-axis represents a date, and the y-axis a quantity. In addition, each point has an associated list of namesMy data is day-by-day without gaps, with a structure such as
var mydata = [ ...
{x: theDate, y: theValue, names: theNames},
... ]
where theNames is an array of strings. I can access these in the tooltip formatter through this.points.point.names, given that the range displayed on the chart is small enough. If I change the x-axes so that the start date and end date are more than roughly a year apart, then the tooltip is not rendered at all.
One of the possible avenues that I have tried but failed with so far is setting the turboThreshold limit to the length of the longest series plus 1. Setting this lets me at least display a graph when mydata.length > 1000 (the default value). However, this only displays the tooltip if the x-axis range is less than 261. Otherwise, the tooltip disappears entirely, as does the point.data object where I'm getting the name from.
I'm also not great at JavaScript, but I was wondering if there were a way to separate the names of the points from the array containing them (in my examples, myData1 and myData2) and somehow access those names from the tooltip function without going through the current point.
Here is the link to the jsFiddle demonstrating this issue.
All help is appreciated!
The problem is in dataGrouping, when disabled works fine: http://jsfiddle.net/34tfg/1/
DataGrouping is method in Highcharts to approximate points and display them when width of the chart is not enough, e.g. how to display 10 000points in a chart of width 1 000px -> 10 points in a one pixel..? And when dataGrouping is used, new points are created, so all your custom options like 'names' etc. are lost (at least not accessible).
Code:
plotOptions: {
line: {
dataGrouping: {
enabled: false
},
turboThreshold: 10000
}
},
Say if my google chart data array looks like below,
Is there a way to target specific data set for google charts and do something.
something like if data = "13 dec 11 Tue" then the point of 56 should use a different color from rest...
["13 Dec 11 Tue",56],
["14 Dec 11 Wed",168],
["15 Dec 11 Thu",181],
["16 Dec 11 Fri",163],
["17 Dec 11 Sat",172]
...
Yes, it is possible, but it requires coding in javascript and cannot be done innately within Google Visualization save within tables using a ColorFormatter. Assuming you want to do it in a chart, you need to write code to do it.
Option 1: Create an Array of Colors
You can use the series configuration option of most charts to set the color of how each series is displayed.
For instance, if I have 3 series, then I can set the following option to turn the second one red:
series: [{}, {color: 'red'}, {}]
This will set no options for series 1 and 3, but change the color of series 2 to red.
So you can loop through your data with Javascript, and create an array of colors to assign to the various series. For instance, if you want any value in column 1 higher than 10 to be red, you could do it as follows:
var colorArray = {};
for(i=0;i<data.getNumberOfRows;i++) {
if(data.getDataValue(i, 1)>10)
colorArray.push({color: 'red'});
else
colorArray.push({});
};
Then you set the options as:
options = {series = colorArray};
Note: The above code has not been checked, it probably has errors since I just typed it out. If it doesn't work, correct my code, but the logic is appropriate.
Option 2: Move the Series
By default, each different column of data will have a different color. You can create a similar loop that checks the value of each item, and moves it to another series. Just create a different for loop that goes through the values you want to check, and if it finds what you're looking for, move the value in to that new series.
This is more complex, but it will give you more flexibility depending on what you want to do (since you have an entirely different series, you can customize it with different line size, or markers, or bar width, or whatever).
Whatever you pick to do, the best thing is to play with it and find something you like and that's easiest for you to code with your data.
Possible duplicate question to Bar chart in Javascript: stacked bars + grouped bars
I'm trying to create a stacked bar chart that lets you compare 2 values (dark and mid blue) to last week's data points (the secondary light blues 'behind').
Starting with multiBarChart() with .stacked(true) first I tried merging both weeks into a single array of 14 bars, where the x position could help group the bars. I tried to form my combined array of objects where .x properties' values are 0, 0.3, 1, 1.3, 2, 2.3, etc.
Unfortunately unlike lineChart() it doesn't use the x value for positioning.
Another idea is to exploit the group .stacked(false), providing 4 items (instead of 2) with the same x value. These then appear overlaid on top of each other instead of stacked.
Here the spacing looks good, but how do I stack these 2 by 2?
Hey I just developed grouped+stacked bar chart on d3.js. It is not NVD3 but it may help you.
Source
Demo
Let me just say up front that I am SO not an nvd3 expert. I'm barely past the getting-started stage myself.
That said, it looks like you're making this too hard on yourself.
I think you really want to send nvd3 two sets of data, with the x's matching between the two. (E.g., (1,y1a) corresponding to (1,y2a), then (2,y2a) with (2,y2b), etc.)
You can see this more clearly by the following:
Head to their Live Code page
Select the Group/Stacked Bar Chart.
Select the Data (JSON) tab.
Replace the first function with the following, and observe the resulting x values.:
function() {
return stream_layers(2,10,.1).map(function(data, i) {
alert( 'Stream '+i+': '+JSON.stringify(data));
return {
key: 'Stream' + i,
values: data
};
});
}
Best as I understand it, that's the model you're looking for.