Optimizing ajax request for a large data set - ajax

Need some help with a ajax use case.
I need to render a graph on a data that has a size of 45 MB approx, I am sending a ajax request on button click to get that data from server and then render the graph on the client side based upon the response.
The problem is due to the content size Content Downloading time is so long which is around 23s. I need to optimize it to around 5s.
Can anyone recommend a solution for this use case?
I have attached the timing stats of the ajax request.
AJAX REQUEST STATS IMAGE
Here is the ajax function
<script>
function generateGraph() {
$.ajax({
type: "GET",
url: "/test",
success: function (data) {
var records = data;
console.log(records.length);
var x = records[0];
var y = records[1];
Plotly.addTraces('myDiv', [
{
x: x,
y: records[1],
type: 'scattergl',
mode: "line"
},
{
x: x,
y: records[2],
type: 'scattergl',
mode: "line"
},
{
x: x,
y: records[3],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[4],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[5],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[6],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[7],
type: 'scattergl'
}, {
x: x,
y: records[3],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[8],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[9],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[10],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[11],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[12],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[13],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[14],
type: 'scattergl',
mode: "line"
}, {
x: x,
y: records[15],
type: 'scattergl',
mode: "line"
},
{
x: x,
y: records[16],
type: 'scattergl',
mode: "line"
},
{
x: x,
y: records[17],
type: 'scattergl',
mode: "line"
},
{
x: x,
y: records[18],
type: 'scattergl',
mode: "line"
}
]);
}
});
}
Plotly.newPlot('myDiv', [{type: 'scattergl'}], {});
</script>

Related

ChartJS+React: toggle showLine in scatter view doesn't work

I have a simple Scatter plot using ChartJS with React. The scatter plot in general has the ability connecting lines between the single datapoints by setting the option 'showLine' in the datasets. I want to have a button to toggle this option (turn showLines on/off). Unfortunately this doesn't work.
If showLines is true in the initalDataSet the change to false doesn't do anything. If showLines is false in the initalDataSet changing it to true crashes ChartJS with the following error:
Uncaught TypeError: line is null
This is a simple example of the problem described:
import React, {
useEffect,
useReducer,
} from "react";
import { Scatter } from "react-chartjs-2";
import Chart from "chart.js/auto";
const initalDataSet = {
datasets: [
{
label: "dataset1",
data: [
{
x: 1,
y: 10,
},
{
x: 3,
y: 15,
},
{
x: 5,
y: 5,
},
{
x: 7,
y: 8,
},
],
borderColor: "red",
showLine: false,
},
{
label: "dataset2",
data: [
{
x: 2,
y: 4,
},
{
x: 4,
y: 6,
},
{
x: 6,
y: 12,
},
{
x: 8,
y: 18,
},
{
x: 10,
y: 10,
},
{
x: 12,
y: 15,
},
{
x: 14,
y: 5,
},
{
x: 16,
y: 8,
},
],
borderColor: "blue",
showLine: false,
},
],
};
const processData = (state, action) => {
switch (action.type) {
case "TOGGLE_LINE":
return {
['datasets']: state.datasets.map((item) => ({
...item,
showLine: (!item['showLine']),
})),
};
default:
return state;
}
};
function App() {
const [plotData, dispatch] = useReducer(processData, initalDataSet);
useEffect(() => {
console.log("debug --->", { datasets: Object.values(plotData) });
}, [plotData]);
return (
<div className="App">
<header className="App-header">
<button
onClick={() => {
dispatch({ type: "TOGGLE_LINE" });
}}
>
Toggle Line View
</button>
<Scatter data={plotData} />
</header>
</div>
);
}
export default App;
I think it must have something to do with the rerendering of the ChartJS component, but I have no idea how to solve it. Does anyone have an idea how to do this?
Thanks!
A possible solution/workaround for this bug can be found here.

ChartJS: How to center monthly bars against a daily line chart?

I'm trying to display total monthly sales and daily stock level. This way you could easily see that you didn't have any sales a particular month because you had low stock. Monthly sales is a bar chart that should be in the center of each month (in between the ticks).
In order to get it close to the middle my data is using the 15th of each month as the date to center it. I would want to know if there is a better way to achieve this?
JSFiddle to play around with: https://jsfiddle.net/8Lydhpqc/3/
const dailyStock = [
{ x: "2017-08-02", y: 1 },
{ x: "2017-08-25", y: 3 },
{ x: "2017-09-10", y: 7 },
{ x: "2017-09-28", y: 0 },
{ x: "2017-10-02", y: 3 },
{ x: "2017-10-24", y: 2 },
{ x: "2017-11-01", y: 1 },
{ x: "2017-11-30", y: 0 },
];
//using the 15th of each month to center it
const monthlyTotal = [
{ x: "2017-08-15", y: 1 },
{ x: "2017-09-15", y: 10 },
{ x: "2017-10-15", y: 5 },
{ x: "2017-11-15", y: 5 },
];
var ctx = document.getElementById("myChart").getContext("2d");
var myChart = new Chart(ctx, {
type: "bar",
data: {
labels: ["2017-08", "2017-09", "2017-10", "2017-11"],
datasets: [
{
label: "sales",
data: data,
backgroundColor: "green",
borderColor: "black",
borderWidth: 1,
order: 2,
},
{
label: "stock",
type: "line",
data: dailyStock,
backgroundColor: "orange",
borderColor: "orange",
fill: false,
order: 1,
},
],
},
options: {
scales: {
xAxes: [
{
type: "time",
time: {
unit: "month",
displayFormats: {
month: "MMM",
},
},
distribution: "linear",
},
],
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});
Welcome to Stackoverflow!
It seems that there is a way better than using the 15th of the month.
You need to add another axis for the bar that is a category type axis. Also its pretty critical that you have "offset: true" on that axis as well. Otherwise it will not center.
In the code below I named that category "bar" and the existing one "line"
I also created a fiddle: https://jsfiddle.net/jyf8ax3e/
var myChart = new Chart(ctx, {
type: "bar",
data: {
labels: ["2017-08", "2017-09", "2017-10", "2017-11"],
datasets: [
{
barPercentage: .7,
xAxisID: "bar",
label: "sales",
data: monthlyTotal,
backgroundColor: "green",
borderColor: "black",
borderWidth: 1,
width: 55,
order: 2,
},
{
label: "stock",
type: "line",
data: dailyStock,
backgroundColor: "orange",
borderColor: "orange",
fill: false,
order: 1,
},
],
},
options: {
scales: {
xAxes: [
{
id: "line",
type: "time",
time: {
unit: "month",
displayFormats: {
month: "MMM",
},
},
distribution: "linear",
},
{
id: "bar",
offset: true,
type: "category",
distribution: "series",
}
],
yAxes: [
{
ticks: {
beginAtZero: true,
},
},
],
},
},
});

How to pass degree Celsius as symbol to YAxis title

How can I pass degree Celcius symbol for yAxis
I have tried all kinds
1. °
2. U+00B0 - unicode
3. ° - html code
but all of them get printed as given and do not print the degree symbol.
You can use suffix property to add suffix in axis labels to do this.
var chart = new CanvasJS.Chart("chartContainer", {
axisY: {
suffix: " °C"
},
data: [{
type: "spline",
yValueFormatString: "#0.## °C",
dataPoints: [
{ x: new Date(2017,6,24), y: 31 },
{ x: new Date(2017,6,25), y: 31 },
{ x: new Date(2017,6,26), y: 29 },
{ x: new Date(2017,6,27), y: 29 },
{ x: new Date(2017,6,28), y: 31 },
{ x: new Date(2017,6,29), y: 30 },
{ x: new Date(2017,6,30), y: 29 }
]
}]
});
chart.render();
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
<div id="chartContainer" style="height: 300px; width: 100%;"></div>

Set the y axis spacing in c3

I have the following chart and I want to make the y axis spacing integers only (when the data to display is low, I get decimals: 0.1, 0.2...). Anyone can help?
var Presence = c3.generate({
bindto: '#presence',
data: {
url: 'ranking.csv',
x:'AC_YEAR',
types: {
Number_students: "bar",
Ranking: 'spline'
},
axes:{
Number_students: "y",
Ranking: "y2"
}
},
axis: {
y: {
label: {
text:"Students",
position: "outer-middle"
},
tick: {
outer: false}
},
y2: {
inverted:true,
show: true,
label: {
text:"Ranking position",
position: "outer-middle"
},
tick: {
outer: false
}
},
x: {
label: {
text:"Year",
position: "outer-center"
},
tick: {outer: false}
}
},
size: {
height: 400,
width: 800
},
});
The csv file looks like this:
AC_YEAR,Number_students,Ranking
2011,1,103
2012,2,30
2014,1,178
2015,1,188
But the csv is changing over time and sometimes the Number of students is 100. So that is why I do not want to fix values on the y axis, only avoid having floats when the Number of students is low (1 or 2)
Thanks in advance!
Set the y tick formatting function to return blanks on non-whole numbers
y: {
label: {
text:"Students",
position: "outer-middle"
},
tick: {
format: function (d) {
return Math.abs(Math.round(d) - d) < 0.001 ? d : "";
},
outer: false
}
},

Generate an array of charts

I want to generate an array of charts and insert them into the DOM.
(I want to use these charts as templates and insert them at the right time)
like that:
Var array = [];
array[0].kendoChart ({// .........});
array[1].kendoChart ({// .........});
array.forEach (function (el) {
$('body').append(el);
})
Tell me how to be?
I would keep an array of the data used to generate the charts, and then generate them at the time of insert.
In HTML provide a container for the charts to be inserted (could be body as in your example):
<div id="chartsContainer" ></div>
Then in script have an array of the data needed to generate the multiple charts, e.g. :
var charts = [
{
chartid: "id1", title: "Chart 1",
data: [{ x: "item1", y: 2}, { x: "item2", y: 4},{ x: "item3", y: 1}]
},
{
chartid: "id2", title: "Chart 2",
data: [{ x: "item1", y: 8}, { x: "item2", y: 3},{ x: "item3", y: 7},{ x: "item4", y: 2}]
},
{
chartid: "id3", title: "Chart 3",
data: [{ x: "item1", y: 1}, { x: "item2", y: 2},{ x: "item3", y: 4} ]
},
];
Finally loop through the array, insert DIVs in the container and create a chart in each DIV:
$("#chartsContainer").empty();
var arrayLength = charts.length;
for (var i = 0; i < arrayLength; i++) {
var div = $('<div id="' + charts[i].chartid + '"></div>');
$("#chartsContainer").append(div);
div.kendoChart({
theme: "Flat",
chartArea: { height: 200 },
dataSource: {data: charts[i].data },
title: { text: charts[i].title},
seriesDefaults: {type: "column"},
series: [{field: "y" }],
categoryAxis: {
field: "x",
majorGridLines: {visible: false },
}
});
}
Working DEMO

Resources