Chartjs - Stacked bar chart data order causes invisible other values - javascript

Ive seen this thread:
Chartjs - Stacked bar chart blocking other values
But still its not what im looking for. As author of previous thread pointed
My problem is that chart js is rendering the bar chart based on the order defined on the dataset. As you can see below, the values at index 0 of the arrays are 2500 and 1000. Since the 2500 was passed first, this will block the bar chart of the 1000 value.
https://jsfiddle.net/6bjy9nxh/352/
labels: ['Italy', 'UK', 'USA', 'Germany', 'France', 'Japan'],
datasets: [
{
label: '2010 customers #',
fillColor: '#382765',
data: [2500, 1902, 1041, 610, 1245, 952]
},
{
label: '2014 customers #',
fillColor: '#7BC225',
data: [1000, 1689, 1318, 589, 1199, 1436]
}
]
As my data is dynamic i dont know what value is higher thus i cant make order static.
Current behaviour if bigger data is passed as first:
Current behaviour
Expected behaviour:
Expected behaviour
Why im not accepting answer from previous thread? Because it sums values on Y axis:
answer from other thread

Perhap you could give each of your dynamic datapoints an index, and then use css z-index to change the order of each individual index?
It seems like you can add custom properties to data in ChartJS. (I've not used it before but I've done something similar using Chartist)

Related

Correct method for graphing programmatically created data with D3

I'm working on an application where datasets have programmatically generated names and are frequently created and destroyed by users. I want to graph these datasets within the application using D3.js.
My datasets are stored like this:
Wavelength
Transducer Output 1
Transducer Output 2
Transducer Output 3
1
19
21
23
3
23
20
21
5
33
23
19
7
33
24
45
etc..
etc..
etc..
etc..
Where wavelength should be mapped along the x axis, and magnitude mapped along the y axis, with an individual line for each set of magnitudes.
I'm struggling to get my head around how one should pass such data into D3.js. Each tutorial I read uses different data formats and different code. I have read the documentation, but it hasn't helped me much in learning how to format my data for D3 either.
What's the correct way to map these datasets onto a graph from within a script? At the moment I'm trying to use d3.csvParse(data), but am unsure where to go from there. I suspect I may be formatting my data awkwardly but am not sure.
Writing up a quick answer to this just incase anyone else gets stuck where I did. Essentially I completely misunderstood how you're supposed to present data to in d3.
Here's a useful guide to understanding d3 data handling
Here's a useful guide on how to use that data once you have it structured correctly
Once I realised that I needed to create an array which represented every point I want drawn things got a lot easier. I created an object with three properties that described a single data point.
Each object has a wavelength, magnitude, and a name.
wavelength is the datapoint's position on the x axis, magnitude is its position on the y axis, and name allows me to differentiate between the different datasets.
let array = [
{name: "dataset 1", wavelength: 2, magnitude: 20}
{name: "dataset 1", wavelength: 3, magnitude: 22}
{name: "dataset 1", wavelength: 4, magnitude: 19}
{name: "dataset 2", wavelength: 2, magnitude: 14} //and so on...
]
From there I could map that onto my graph with
svg.append("path")
.data(array)
.attr("d", d3.line()
.x(function(d) {return x(d.wavelength)})
.y(function(d) {return y(d.magnitude)})
.z(function(d) {return z(d.name)});
You can also group the data by name using d3.group() and iterate through that through your data manually, drawing each line individually
Thanks #Alexander Nied and #Gerardo Furtado for nudging me back on track!

Vue Chart.js -- can I give a line chart a default value for missing data?

I'm creating a line chart with Vue.js, but there are gaps in the data I'm passing to renderChart(). I haven't been able to find anything so far in the documentation but I'm still curious -- is there a way to fill in those gaps with a default value? I'd use zero in this case but it would be cool if it was configurable. Or is my best bet to backfill the data with dummy values before passing it in to renderChart()?
I'm assuming you have some kind of regular time interval for your labels.
In Chart.js datasets are mapped to labels by their indexes in the arrays. Chart.js doesn't really know where the "gaps" in your data are. Also Chart.js doesn't know the date interval used for your label. I assume this choice of design in Chart.js is for performance reasons.
This would work as expected:
data: [1,0,0,10]
labels: ['June','July','Aug', 'Sept']
Here Chart.js would assume the first two values are for June and July:
data: [1,10]
labels: ['June','July','Aug','Sept']
Here Chart.js has no idea that July and Aug are missing:
data: [1,10]
labels: ['June','Sept']
If you API returns data like this:
{'June': 1, 'July': 0, 'Aug': 0, 'Sept': 10}
Then you can just do this:
const labels = Object.keys(response);
const datasets = [];
datasets.push({
label: 'Line 1',
data: labels.map(date => response[date]),
});
this.renderChart({
labels,
datasets,
});
You can use something like this in your backend to fill out the empty dates/months etc.
$interval = \DateInterval::createFromDateString('1 month');
$datePeriod = new \DatePeriod($begin, $interval, $end);
foreach ($datePeriod as $dt) {
if (!isset($data[$dt->format('Y.m')])) {
$data[$dt->format('Y.m')] = 0;
}
}
Hope this helps.

Incorrect values on Highcharts (compared to input)

I have a (Highcharts) graph with a percentage over time. The input for my series looks something like:
series: [{
name: "Percentage",
data: [
[1472515200000, 49],
[1472601600000, 48.83],
[1472688000000, 49.6],
[1472774400000, 48.77]
]
}]
However on the actual chart (areaspline) I get different values:
30 Aug, 48.91
31 Aug, 49.36
1 Sep, 49.6
2 Sep, 48.87
Not entirely sure why this is the case, I'm assuming it's because the graph has a datetime type and it's figuring out the average over time. Is there a way I can make the values exact as they are input? Couldn't find anything in docs
Thanks for any ideas/help/advice.
Upon further research, it seems like it's not so much a Highcharts problem but a React one. I seem to be getting different values on each render. Will look into this further and update for the curious.
Problem seemed to be related to React re-rendering and therefore recalculating my percentage values - not a Highcharts issue. Thanks for everyone who commented, bit of a wild goose chase.
Jamie, to make the input values be taken literally, you need to either leave the type value of your x-axis unset or change it to type: 'literal'.
Here's a basic fiddle I created with your data to show how it can be interpreted exactly as input (vs. converted to dates): http://jsfiddle.net/brightmatrix/vtLswcex/1/
$(function () {
Highcharts.setOptions({
lang: {
thousandsSep: ',' // adds comma for axis labels
}
});
Highcharts.chart('container', {
xAxis: {
labels: {
formatter: function() {
return Highcharts.numberFormat(this.value,0);
}
}
},
series: [{
name: "Percentage",
data: [
[1472515200000, 49],
[1472601600000, 48.83],
[1472688000000, 49.6],
[1472774400000, 48.77]
]
}]
});
});
Note that I've added formatting for the x-axis labels, as well as a thousands separator in the Highcharts.setOptions() function, so that your labels will be more easily readable as trillions.
Does this help answer your question? If you are instead looking for a better way to format time-specific data, the comment by #morganfree is well worth looking into.

Highcharts with dynamic yaxis labels as strings

I've been trying to add some custom yAxis labels to highcharts but I've not been able to so far. I've tried using formatter from a predefined array of strings and I've tried addAxis method but that doesn't get me the results I'm looking for.
Basically I have some numbers (lets say 4 and 4000) and I want to have these as my yLabels. However, I do NOT want the giant space between them. They need to be one right after the other and in ascending order. I cannot figure out how to do this leaving them as integers and I cannot figure out how to dynamically add them to highcharts as strings. I'm not even sure if this is possible
Any help would be greatly appreciated.
Here is the Y-axis label formatter documentation from Highcharts you're probably looking for. I wrote this fiddle to simulate the custom y-axis functionality you were wanting, although I'm not sure how you want to map those values to the x-axis data. This should give you a good starting point.
Code for reference:
$('#container').highcharts({
yAxis: {
categories: ['4', '4000', 'Foobar'],
labels: {
formatter: function () {
return this.value;
}
}
},
series: [{
data: [0, 1, 2]
}]
});
This stackoverflow question may also help although I noticed some dead links.

Highcharts - Stacked column data series

Im working with stacked column using Highcharts.
The data series im constructing is similar to this
series: [{
name: 'Apples',
data: [['2014-01-01',5], ['2014-01-02',3], ['2014-01-04',2], ['2014-01-05',7], ['2014-01-06',8]]
}, {
name: 'Oranges',
data: [['2014-01-01',3], ['2014-01-02',7], ['2014-01-04',9], ['2014-01-05',11], ['2014-01-06',19]]
}, {
name: 'Grapes',
data: [['2014-01-01',15], ['2014-01-02',23], ['2014-01-03',12], ['2014-01-05',17], ['2014-01-06',18]]
}]
http://jsfiddle.net/emgq47px/
If you take a closer look at the data, im missing 2014-01-04 data for Apples but instead the data is stacked on 2014-01-03.
One way of solving this would be to prepopulate categories and follow the same order for inserting my y values but that wont be a good way to solve as i may deal with large data sets down the line.
Any tips to head in the right direction is greatly appreciated.
UPDATE:
I'm populating my x and y co-ordinates with values from database. Database gives me date in (YYYY-mm-dd) format. So i'm converting that string to epoch time using strtotime function in PHP strtotime($res[0])
But then when I populate draw the highchart, i see wrong dates. I checked with online available epoch converters and it looks like conversion is right but i still cant figure out whats wrong here.
Even the x axis ticks seems to be slightly off.
Many thanks for your suggestions.
http://jsfiddle.net/emgq47px/3/
RESOLVED:
I had to multiply epoch time with 1000. This works.
Original answer: HighCharts - timeseries chart - irregular datetime interval on xAxis
Probably the best way is to use a datetime axis. This allows highcharts to know the data contains dates, and it can sort out the axis properly.
xAxis: {
lineWidth: 2,
type: 'datetime'
},
Once you do this, you need to supply valid date times in your data like this:
data: [[Date.UTC(2014, 0, 1),5],
[Date.UTC(2014, 0, 2),3],
[Date.UTC(2014, 0, 4),2],
[Date.UTC(2014, 0, 5),7],
[Date.UTC(2014, 0, 6),8]]
Note, months go from 0 to 11, not 1 to 12, so zero is January.
http://jsfiddle.net/0ofLx86d/
The problem is that you are marking x-axis type is category
xAxis: {
lineWidth: 2,
type: 'category'
},
So when you assign data data: [['2014-01-01',5], ['2014-01-02',3], like this to it then the first value is considered as category so when you assign ['2014-01-03',12] as last then it replaces previous one ['2014-01-04',12]. You can test it by keeping first two as 03 and last one as 04, then it will take 04 and not show 03.
Solution
Replace
type: 'category' to 'datetime'
and date to epoch time
data: [[1388534400000,5], [1388620800000,3], [1388793600000,2], [1388880000000,7]]
You can use custom function for label if you want to display date on x-axis in different format or use Date.UTC
Demo

Categories