I'm not able to fill a Chart with my Array.
This is the Json: https://pastebin.com/KLUWqDFS
I'm trying to create a "Area" chart and fill it. Each element in the Json is half an hour.
let series = []
for(let i = 0; i < props.rrd.length; i++) {
series.push({
data: [
{
x: props.rrd[i].cpu * 100,
y: moment(props.rrd[i].time).format('hh:mm')
}
]
})
}
const chartOptions = {
yaxis: {
show: true
},
xaxis: {
show: true
}
}
This is what I'm using. Somehow all I get is this:
My Result
Eventhough it should show me the last 24 hours in the chart.
Related
I am trying to figure out how to render a section of each column in a simple, single series, column chart with multiple colors. Using series.zones:
series: [
{
name: "Mod",
colorByPoint: true,
data: seriesData,
zones: [
{ value: 101, color: '#1D681B' },
{ value: 121, color: '#ECC518' },
{ color: '#D50D0D' }
]
}
]
I can get each column to be a different color based on the zone that the y value is within.
In my example above the zone are:
0 through 100 should be green
101 to 120 should be yellow
121 and above should be red
The above works to an extent, but looks like the following:
However, what my boss wants is something like this:
Can this be achieved using highcharts?
Instead of zones you can use stacked columns. Below is a simple example of how you can automatically calculate series structure:
const steps = [100, 20];
const data = [42, 100, 96, 120, 110, 90, 140];
const series = [{
color: '#1D681B',
data: []
}, {
linkedTo: ':previous',
color: '#ECC518',
data: []
}, {
linkedTo: ':previous',
color: '#D50D0D',
data: []
}];
data.forEach((dataEl, i) => {
let rest = dataEl;
let counter = 0;
let value;
while (rest > 0) {
value = steps[counter] < rest ? steps[counter] : rest;
series[counter].data.push({
x: i,
y: value
});
rest -= value;
counter++;
}
});
Highcharts.chart('container', {
chart: {
type: 'column'
},
yAxis: {
reversedStacks: false
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series
});
Live demo: http://jsfiddle.net/BlackLabel/3h6o0ncg/
Docs: https://www.highcharts.com/docs/advanced-chart-features/stacking-charts
So, What I have is a condition in a MySQL to show the first 1000 data points first and then the other 2000 datapoints after that in Highcharts.
if lastindex==0:
cur.execute("SELECT data,value FROM table where id<1001")
else:
cur.execute("SELECT data,value FROM table where id>1001 and id<3000")
data = cur.fetchall()
//python Code to fetch SQL data
Now what I am doing is that I am rendering that data into the Highcharts, the data is being rendered. but the problem arises that after showing the first 1000 data points, the Highcharts value starts from 0 and then shows the other 2000 points
the data is not displaying continuously as it should plot the send array data just after the end of the first data.
I think the Highcharts is being called Twice, What can I do to append the 2nd set of data to the first set without reloading the whole chart.
Here's a snip of my Highchart's js
Highcharts.chart("chartcontainer", {
chart: {
type: 'line',
animation: Highcharts.svg, // don't animate in old IE
marginRight: 10,
events: {
load: function() {
var series = this.series[0],
chart = this;
setInterval(function() {
//some logic regarding the chart
//..
v = {
y: y,
x: x
};
console.log("V value", v);
series.addSeries(v, false, true);
counter++;
localcounter++;
} else
{
oldcounter=counter;
flagToreload=1;
}
}, 1000/130);
setInterval(function() {
chart.redraw(false);
}, 100);
}
}
},
time: {
useUTC: false
},
title: {
text: 'Live random data'
},
xAxis: {
type: 'Value',
gridLineWidth: 1
},
yAxis: {
title: {
text: 'Value'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}],
gridLineWidth: 1
},
tooltip: {
headerFormat: '<b>{series.name}</b><br/>',
pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
},
exporting: {
enabled: false
},
series: [{
animation: false,
name: 'Random data',
data: (function() {
// generate an array of random data
var data = [],
time = counter,
i;
for (i = -1000; i <= 0; i += 1) {
data.push([
counter,
null
]);
}
return data;
}())
}]
});
What I want is just to append the event data rather than loading the whole chart.
How can I reload a particular Highchart value without reloading the whole chart ?
What do you think about updating the current series with new data, which will be an array of old data merged with the new one?
chart: {
events: {
load(){
let chart = this,
currentSeries = chart.series[0],
newData;
newData = [...currentSeries.userOptions.data, ...data1]
setTimeout(()=> {
chart.series[0].update({
data: newData
})
}, 5000)
}
}
},
See the demo
I have plotted a stacked bar chart for 4 data values that I have for every U.S. state. The CSV file I have been working off of looks like this:
Here's the JS code I wrote for the stacked bar chart:
// Read the data from CSV
d3.csv('https://raw.githubusercontent.com/krithikaragha/ResPy/master/Flask%20App/static/data/tobacco_use_by_state.csv', function(data) {
var chartData = []; // Array containing all the traces
function makeTrace(d) { // Function to make all 50 traces
return {
x: ["Smokes Everyday", "Smokes Somedays", "Former Smoker", "Never Smoked"],
y: [d.smokesEveryday, d.smokesSomedays, d.formerSmoker, d.neverSmoked],
name: d.state,
type: 'bar'
}
}
// Loop through all rows of the data
for(var i = 0; i < data.length; i++) {
// Call makeTrace to create a trace with index i
chartData.push(makeTrace(data[i]));
// Define a chart layout
var layout = {
barmode: 'stack',
width: 1200,
height: 800
};
// Plot the stacked bar chart
Plotly.newPlot('bar', chartData, layout);
}
});
The resulting stacked bar chart ended up looking like this:
The result I want to achieve is: I want each U.S. state to have its own bar which is stacked with respective 4 values (smokesEveryday, smokesSomedays, formerSmoker and neverSmoked)
Is there any way I can achieve this? Thanks in advance.
I figured it out myself.
Turns out, I had to make four separate traces for each of the 4 values I needed. So I looped through the data and created arrays for each column - smokedEveryday, smokesSomedays, formerSmoker and neverSmoked and a last array states to hold the state's abbreviations.
Then I created 4 individual traces with x-axis holding the states array and y-axis holding the respective smoking array.
Here's the modified code snippet:
// Read the data from CSV
d3.csv('https://raw.githubusercontent.com/krithikaragha/ResPy/master/Flask%20App/static/data/tobacco_use_by_state.csv', function(data) {
var states = [];
var smokesEveryday = [];
var smokesSomedays = [];
var formerSmoker = [];
var neverSmoked = [];
// Loop through all rows of the data
for(var i = 0; i < data.length; i++) {
states.push(data[i].abbr);
smokesEveryday.push(data[i].smokesEveryday);
smokesSomedays.push(data[i].smokesSomedays);
formerSmoker.push(data[i].formerSmoker);
neverSmoked.push(data[i].neverSmoked);
}
var smokesEverydayTrace = {
x: states,
y: smokesEveryday,
name: 'Smokes Everyday',
type: 'bar'
};
var smokesSomedaysTrace = {
x: states,
y: smokesSomedays,
name: 'Smokes Somedays',
type: 'bar'
};
var formerSmokerTrace = {
x: states,
y: formerSmoker,
name: 'Former Smoker',
type: 'bar'
};
var neverSmokedTrace = {
x: states,
y: neverSmoked,
name: 'Never Smoked',
type: 'bar'
};
var data = [neverSmokedTrace, formerSmokerTrace, smokesSomedaysTrace, smokesEverydayTrace];
var layout = {
barmode: 'stack',
title: "Percentage of Tobacoo Use by State",
xaxis: {
title: {
text: "Tobacco Use"
},
tickangle: 45
},
yaxis: {
title: {
text: "Percentage"
}
},
bargap: 0.4,
width: 1250,
height: 800
};
Plotly.newPlot('bar', data, layout);
});
I would like to have the y-axis only with the min/max values of my data.
I tried to use the d3 directive but without results.
I had a look at google but I didn't find an answer to achieve this behaviour.
Below the code:
$.getJSON('assets/json/chartc3.json', function(data)
{
scene=data;
var chart = c3.generate({
bindto: '#chartc3',
data:
{
json: scene,
keys:
{
x: 'round',
value: ['Marketable', 'Total Requested Capacity', 'Your Bid'],
},
types: {
Marketable: 'area'
},
colors: {
Marketable: '#A09FA2',
'Total Requested Capacity': '#272E80',
'Your Bid': '#8EBF60'
}
},
axis:
{
x: {
tick:
{
culling:
{
max: 10
}
},
type: 'category'
},
y:
{
min: 0,
padding : {
bottom : 0
},
tick:
{
values: [[0], [***d3.max(scene)]***],
format: function (d) { return d3.format(',f')(d) +' kWh/h' }
//or format: function (d) { return '$' + d; }
}
}
}.........
How could I achieve the result described above ? d3.max(scene) returns NaN.
Well the problem is scene is not an array its a json object.
var k = d3.max([1,5,2])
k will be 5
so you will need to pass an array of elements which constitute your y ordinals.
you need to use
d3.max(arr, function(d){return numberic value});
or
var arr = scene.map(function(d){return ...the number value..})
y:{
min:d3.min(arr),
max:d3.max(arr)
},
the function depends on the array element of your data.
I used a little function to calculate the max by myself.
var maxs=0;
for (var j=0; j<scene.length; j++) {
var maxtemp=Math.max(scene[j].Marketable, scene[j]['Your Bid'], scene[j]['Total Requested Capacity']);
maxs=Math.max(maxs, maxtemp);
}
I'm using Highcharts to draw a spline. This works good.
I'm using secondary series (columns) for another data.
My problem is: how to set column height to be matched with spline.
As far i've done this: jsfiddle
Columns have height almost i need, but not all.
It is possible at all?
Relevant code:
$('#chart').highcharts({
title: {text: 'Chart'},
chart: {
type: 'spline'
},
xAxis: {
title: {
text: 'X-Axis'
}
},
yAxis: {
title: {
text: 'Y-Axis'
},
labels: {
enabled: false
}
},
series: [{
name: 'Chart',
data: chdata,
marker: {
enabled: false
},
}],
legend: {
enabled: false
}
});
var chartObj = Highcharts.charts[$('#chart').attr('data-highcharts-chart')];
var d = [];
for(var i = 0; i < ldata.length; i++) {
d.push([ldata[i],getYValue(chartObj,0,getClosest(ldata[i],bdata[0]))]);
}
chartObj.addSeries({
type: 'column',
pointWidth: 1,
borderWidth: 0,
data: d
});
I've tried even with plotLines, but it have height of whole chart.
Thanks,
Bartek
Rather than plotting the height of the closest point, try plotting the average height of the points either side of your bar.
You can get even closer if you work out a linear best fit for your bar on the line between the points either side. Something like:
function getY(xVal,points) {
var higher = 0;
var lower=0;
for(var i=0;i<points.length;i++){
if (points[i][0] > xVal) {
higher=i;
lower=i-1;
break;
}
}
return points[lower][1] + ((points[higher][1]-points[lower][1])*(xVal-points[lower][0])/(points[higher][0]-points[lower][0]));
};
http://jsfiddle.net/5h471o3d/