Regression that fits best scatter plot - javascript

I have the following scatter plot plotted and I want to add a linear, polynomial regression (the one that fits best) to my data. Is there any easy way to do it?
My chart is an easy one, done by c3 library v4 (depending on d3 v3):
<div id="chart2"></div>
<script>
var chart = c3.generate({
bindto: '#chart2',
data: {
url: '../static/CSV/Chart_data/grades_access.csv'+(new Date).getTime(),
x:'Access_grade',
type: 'scatter'
},
axis: {
y: {
label: {
text:"Average grade",
position: "outer-middle"
},
min:1,
max:9
},
x: {
label: {
text:"Access grade PAU",
position: "outer-center"
},
min:9,
max:14
}
},
size: {
height: 400,
width: 800
},
zoom: {
enabled: true
},
legend: {
show: true,
position: 'inset',
inset: {
anchor: 'top-right',
x: 20,
y: 300,
step: 1
}
}
});
</script>
And grades_access.csv is:
Access_grade,Subject
9.85,2.5
10.64,8.1
10.0,3.2
10.92,4.0
11.69,2.9
11.79,7.8
11.03,5.0
10.47,6.2
...
Could anyone give me a hint? I want a simple thing, not too sofisticated. But with the equation of the regression if possible :)
Thanks!

I've answered this question a couple time for other libraries but never c3.js. Here's code to fit a linear regression using a simple least squared method. It does it onrendered so that you can still use c3's ability to fetch and parse your csv file:
<div id="chart2"></div>
<script>
var chart = c3.generate({
bindto: '#chart2',
data: {
url: 'data.csv',
x: 'Access_grade',
type: 'scatter'
},
axis: {
y: {
label: {
text: "Average grade",
position: "outer-middle"
},
min: 1,
max: 9
},
x: {
label: {
text: "Access grade PAU",
position: "outer-center"
},
min: 9,
max: 14
}
},
size: {
height: 400,
width: 800
},
zoom: {
enabled: true
},
legend: {
show: true,
position: 'inset',
inset: {
anchor: 'top-right',
x: 20,
y: 300,
step: 1
}
},
onrendered: function(c) {
var points = chart.data()[0].values.map((d) => [d.x, d.value]),
slopeIntercept = slopeAndIntercept(points),
fitPoints = chart.data()[0].values.map((d) => slopeIntercept.slope * d.x + slopeIntercept.intercept);
chart.load({
columns: [
['Regression'].concat(fitPoints)
],
type: 'line'
});
}
});
// simple linear regression
slopeAndIntercept = function(points) {
var rV = {},
N = points.length,
sumX = 0,
sumY = 0,
sumXx = 0,
sumYy = 0,
sumXy = 0;
// can't fit with 0 or 1 point
if (N < 2) {
return rV;
}
for (var i = 0; i < N; i++) {
var x = points[i][0],
y = points[i][1];
sumX += x;
sumY += y;
sumXx += (x * x);
sumYy += (y * y);
sumXy += (x * y);
}
// calc slope and intercept
rV['slope'] = ((N * sumXy) - (sumX * sumY)) / (N * sumXx - (sumX * sumX));
rV['intercept'] = (sumY - rV['slope'] * sumX) / N;
rV['rSquared'] = Math.abs((rV['slope'] * (sumXy - (sumX * sumY) / N)) / (sumYy - ((sumY * sumY) / N)));
return rV;
}
</script>
Here's a running example.

Related

Changing xaxis label from echarts library

var data = [];
var dataCount = 10;
var startTime = +new Date();
var categories = ['categoryA', 'categoryB', 'categoryC'];
var types = [
{name: 'JS Heap', color: '#7b9ce1'},
{name: 'Documents', color: '#bd6d6c'},
{name: 'Nodes', color: '#75d874'},
{name: 'Listeners', color: '#e0bc78'},
{name: 'GPU Memory', color: '#dc77dc'},
{name: 'GPU', color: '#72b362'}
];
// Generate mock data
echarts.util.each(categories, function (category, index) {
var baseTime = startTime;
for (var i = 0; i < dataCount; i++) {
var typeItem = types[Math.round(Math.random() * (types.length - 1))];
var duration = Math.round(Math.random() * 10000);
data.push({
name: typeItem.name,
value: [
index,
baseTime,
baseTime += duration,
duration
],
itemStyle: {
normal: {
color: typeItem.color
}
}
});
baseTime += Math.round(Math.random() * 2000);
}
});
function renderItem(params, api) {
var categoryIndex = api.value(0);
var start = api.coord([api.value(1), categoryIndex]);
var end = api.coord([api.value(2), categoryIndex]);
var height = api.size([0, 1])[1] * 0.6;
var rectShape = echarts.graphic.clipRectByRect({
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height
}, {
x: params.coordSys.x,
y: params.coordSys.y,
width: params.coordSys.width,
height: params.coordSys.height
});
return rectShape && {
type: 'rect',
shape: rectShape,
style: api.style()
};
}
option = {
tooltip: {
formatter: function (params) {
return params.marker + params.name + ': ' + params.value[3] + ' ms';
}
},
title: {
text: 'Profile',
left: 'center'
},
dataZoom: [{
type: 'slider',
filterMode: 'weakFilter',
showDataShadow: false,
top: 400,
height: 10,
borderColor: 'transparent',
backgroundColor: '#e2e2e2',
handleIcon: 'M10.7,11.9H9.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7v-1.2h6.6z M13.3,22H6.7v-1.2h6.6z M13.3,19.6H6.7v-1.2h6.6z', // jshint ignore:line
handleSize: 20,
handleStyle: {
shadowBlur: 6,
shadowOffsetX: 1,
shadowOffsetY: 2,
shadowColor: '#aaa'
},
labelFormatter: ''
}, {
type: 'inside',
filterMode: 'weakFilter'
}],
grid: {
height:300
},
xAxis: {
min: startTime,
scale: true,
axisLabel: {
formatter: function (val) {
return Math.max(0, val - startTime) + ' ms';
}
}
},
yAxis: {
data: categories
},
series: [{
type: 'custom',
renderItem: renderItem,
itemStyle: {
normal: {
opacity: 0.8
}
},
encode: {
x: [1, 2],
y: 0
},
data: data
}]
};
Hi, everyone!! I am working on the echarts library, the only thing i want to change data is the axisLabel from Xaxis part.
What i mean is, for example, "2019-11-5, 2019-11-6...."and so on. So, i hope someone can help me out, thank you so much!!!
Hi, everyone!! I am working on the echarts library, the only thing i want to change data is the axisLabel from Xaxis part.
What i mean is, for example, "2019-11-5, 2019-11-6...."and so on. So, i hope someone can help me out, thank you so much!!!
First, create an array of dates like
var dates = ['2019-11-5','2019-10-3','2019-2-2','2019-1-4','2019-12-5'];
then in xAxis -> axisLabel return date
axisLabel: {
formatter: function (val,index) {
return dates[index];
}
}

Adding Labels to the Left or Right of Highcharts Funnel Visualization

My current visualization is as follows:
$(function() {
var dataEx = [
['1 Visit', 352000],
['2 Visits', 88000],
['3+ Visits', 42000]
],
len = dataEx.length,
sum = 0,
minHeight = 0.05,
data = [];
//specify your percent of prior visit value manually here:
var perc = [100, 25, 48];
for (var i = 0; i < len; i++) {
sum += dataEx[i][1];
}
for (var i = 0; i < len; i++) {
var t = dataEx[i],
r = t[1] / sum;
data[i] = {
name: t[0],
y: (r > minHeight ? t[1] : sum * minHeight),
percent: perc[i], // <----- this here is manual input
//percent: Math.round(r * 100), <--- this here is mathematical
label: t[1]
}
}
console.log(dataEx, data)
$('#container').highcharts({
chart: {
type: 'funnel',
marginRight: 100,
events: {
load: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
var bBox = p.dataLabel.getBBox()
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
'text-anchor': 'middle',
y: p.labelPos.y - (bBox.height / 2)
})
})
},
redraw: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
'text-anchor': 'middle',
y: p.labelPos.y - (bBox.height / 2)
})
})
}
},
},
title: {
text: 'Guest Return Funnel',
x: -50
},
tooltip: {
//enabled: false
formatter: function() {
return '<b>' + this.key +
'</b><br/>Percent of Prior Visit: '+ this.point.percent + '%<br/>Guests: ' + Highcharts.numberFormat(this.point.label, 0);
}
},
plotOptions: {
series: {
allowPointSelect: true,
borderWidth: 12,
animation: {
duration: 400
},
dataLabels: {
enabled: true,
connectorWidth: 0,
distance: 0,
formatter: function() {
var point = this.point;
console.log(point);
return '<b>' + point.name + '</b> (' + Highcharts.numberFormat(point.label, 0) + ')<br/>' + point.percent + '%';
},
minSize: '10%',
color: 'black',
softConnector: true
},
neckWidth: '30%',
neckHeight: '0%',
width: '50%',
height: '110%'
//old options are as follows:
//neckWidth: '50%',
//neckHeight: '50%',
//-- Other available options
//height: '200'
// width: pixels or percent
}
},
legend: {
enabled: false
},
series: [{
name: 'Unique users',
data: data
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://code.highcharts.com/highcharts.js"></script>
<script src="http://code.highcharts.com/modules/funnel.js"></script>
<script src="http://code.highcharts.com/modules/exporting.js"></script>
<div id="container" style="width: 500px; height: 400px; margin: 0 auto"></div>
I would like to do the following (a photo that clarifies what I would like is HERE):
Put the category names "1 Visit", "2 Visits", "3 Visits" to the LEFT of
the funnel.
Arrange the number of guest amount and percent for each category of the
funnel so that it appears like (INSIDE the funnel):
352K 100%
Right now I have the values as the full number like 352000 but I'm
wondering if there's a way to make all numbers with 000 at the end into
a "K" at the end.
It would be great if I could also add labels for those two values AT THE
TOP of the funnel ("Guests" and "Percent of Prior Visit").
Add 2 more labels to the RIGHT of the funnel called "Q1/17 TTM" and "Avg
Value" and have values be placed for each category of the funnel
below the labels. The values for "Q1/17 TTM" should be red and the
values for "Avg Value" should be gray.
The values for "Q1/17 TTM" begin at the "2 Visits" and end at the very
bottom (under the last category)
Values for "Avg Value" begin at the first category and end at the last
category.
At the very bottom of the visualization, have a value. Don't worry about
what this is (and this is the value $12.9M in the photo).
And I want these changes to still make the data processing algorithm to visualize small values work. I would really appreciate the help! Thank you.
There isn not any option in Highcharts to handle more than one datalabels, but you can use text SVGRenderer to add additional text elements, for example:
events: {
render: function() {
var chart = this;
Highcharts.each(chart.series[0].data, function(p, i) {
var bBox = p.dataLabel.getBBox();
p.dataLabel.attr({
x: (chart.plotWidth - chart.plotLeft) / 2,
'text-anchor': 'middle',
y: p.labelPos.y - (bBox.height / 2)
});
if (p.dataLabel1) {
p.dataLabel1.destroy();
p.dataLabel2.destroy();
}
p.dataLabel1 = chart.renderer.text(p.name, p.dataLabel.x - 150, p.dataLabel.y + chart.plotTop - bBox.y).add();
p.dataLabel2 = chart.renderer.text('some Text', p.dataLabel.x + 150, p.dataLabel.y + chart.plotTop - bBox.y).add();
});
}
}
Live demo: https://jsfiddle.net/BlackLabel/w2cs4ufe/1/
API Reference: https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#text

HTML Content to Javascript Code

I am trying to take the content in a div tag and turn it into Javascript code. The reason for this is to take the div information and convert it into a Highchart data series.
HTML Content
<div id="data">{name: 'Point 1',x: Date.UTC(2014, 11, 1),x2: Date.UTC(2014, 11, 8),y: 0},{name: 'Point 2',x: Date.UTC(2014, 12, 1),x2: Date.UTC(2014, 12, 8),y: 0},</div>
Javascript/snippet Content
$(function () {
var newdata = $("#data");
(function (H) {
var defaultPlotOptions = H.getOptions().plotOptions,
columnType = H.seriesTypes.column,
each = H.each;
defaultPlotOptions.xrange = H.merge(defaultPlotOptions.column, {});
H.seriesTypes.xrange = H.extendClass(columnType, {
type: 'xrange',
parallelArrays: ['x', 'x2', 'y'],
requireSorting: false,
animate: H.seriesTypes.line.prototype.animate,
/**
* Borrow the column series metrics, but with swapped axes. This gives free access
* to features like groupPadding, grouping, pointWidth etc.
*/
getColumnMetrics: function () {
var metrics,
chart = this.chart;
function swapAxes() {
each(chart.series, function (s) {
var xAxis = s.xAxis;
s.xAxis = s.yAxis;
s.yAxis = xAxis;
});
}
swapAxes();
this.yAxis.closestPointRange = 1;
metrics = columnType.prototype.getColumnMetrics.call(this);
swapAxes();
return metrics;
},
translate: function () {
columnType.prototype.translate.apply(this, arguments);
var series = this,
xAxis = series.xAxis,
metrics = series.columnMetrics;
H.each(series.points, function (point) {
var barWidth = xAxis.translate(H.pick(point.x2, point.x + (point.len || 0))) - point.plotX;
point.shapeArgs = {
x: point.plotX,
y: point.plotY + metrics.offset,
width: barWidth,
height: metrics.width
};
point.tooltipPos[0] += barWidth / 2;
point.tooltipPos[1] -= metrics.width / 2;
});
}
});
/**
* Max x2 should be considered in xAxis extremes
*/
H.wrap(H.Axis.prototype, 'getSeriesExtremes', function (proceed) {
var axis = this,
dataMax = Number.MIN_VALUE;
proceed.call(this);
if (this.isXAxis) {
each(this.series, function (series) {
each(series.x2Data || [], function (val) {
if (val > dataMax) {
dataMax = val;
}
});
});
if (dataMax > Number.MIN_VALUE) {
axis.dataMax = dataMax;
}
}
});
}(Highcharts));
// THE CHART
$('#container').highcharts({
chart: {
type: 'xrange'
},
title: {
text: 'Highcharts X-range study'
},
plotOptions: {
series: {
events: {
mouseOver: function () {
var cur = this;
Highcharts.each(this.chart.series, function (series) {
if (series !== cur) {
series.group.animate({
opacity: 0.2
}, {
duration: 150
});
} else {
series.group.animate({
opacity: 1
}, {
duration: 150
});
}
});
},
mouseOut: function () {
this.group.animate({
opacity: 1
}, {
duration: 150
});
}
}
}
},
xAxis: {
type: 'datetime'
},
yAxis: {
title: '',
categories: [],
},
series: [$(newdata).text()]
}]
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div id="data">{name: 'Point 1',x: Date.UTC(2014, 11, 1),x2: Date.UTC(2014, 11, 8),y: 0},{name: 'Point 2',x: Date.UTC(2014, 12, 1),x2: Date.UTC(2014, 12, 8),y: 0},</div>
It pulls the content as text and does not create it as code. Can this be done?
If all of the contents of the #data element is properly formatted, all you'll actually have to do is grab the inner html of that element and parse it into JSON.
// This is the contents of #data as a String
var data_as_a_string = document.getElementById("data").innerHTML;
// And here it is "in javascript" as an Object
var data_as_an_object = JSON.parse( data_as_a_string );
you can try eval function
The eval() function evaluates JavaScript code represented as a string.
eval(string)
eval(" var s='hello'; alert(s);");

Restacking cumulative columns in Highcharts marimekko charts

I've got a basic variable width column chart (aka Marimekko) set up using Highcharts but am having trouble getting it to restack the columns properly to eliminate the data gap once a series has been removed or hidden.
JSFIDDLE DEMO <-- I've set up a demo of the issue here.
You'll notice clicking on a legend item removes the series from the chart, but it also removes all of the following data points in the array (i.e. clicking on series C removes series C, D, and E whereas it should redraw to A-B-D-E). Since the y-axis data is meant to display a cumulative sum of all series, these should re-shuffle as adjacent columns with no gaps. How can I get this to render properly?
THIS POST uses similar demo code and attempting to solve the same problem, however the answer is somewhat elusive and I am unable to get it working.
Thanks in advance!
$(function () {
var dataArray = [
{ name: 'A', x: 200, y: 120 },
{ name: 'B', x: 380, y: 101 },
{ name: 'C', x: 450, y: 84 },
{ name: 'D', x: 198, y: 75 },
{ name: 'E', x: 95, y: 55 }
];
function makeSeries(listOfData) {
var sumX = 0.0;
for (var i = 0; i < listOfData.length; i++) {
sumX += listOfData[i].x;
}
var allSeries = []
var x = 0.0;
for (var i = 0; i < listOfData.length; i++) {
var data = listOfData[i];
allSeries[i] = {
name: data.name,
data: [
[x, 0], [x, data.y],
{
x: x + data.x / 2.0,
y: data.y,
dataLabels: { enabled: false, format: data.x + ' x {y}' }
},
[x + data.x, data.y], [x + data.x, 0]
],
w: data.x,
h: data.y
};
x += data.x + 0;
}
return allSeries;
}
$('#container').highcharts({
chart: { type: 'area' },
xAxis: {
tickLength: 0,
labels: { enabled: true}
},
yAxis: {
title: { enabled: false}
},
plotOptions: {
series: {
events: {
legendItemClick: function () {
var pos = this.index;
var sname = this.name;
var chart = $('#container').highcharts();
while(chart.series.length > 0) {
chart.series[pos].remove(true);
}
dataArray[pos]= { name: sname, x: 0, y: 0 };
chart.series[0].setData(dataArray);
}
}
},
area: {
lineWidth: 0,
marker: {
enabled: false,
states: {
hover: { enabled: false }
}
}
}
},
series: makeSeries(dataArray)
});
});

Creating Highchart Graph with JavaScript

I want to create high chart graph .
Here is FIDDLE LINK of My code.
I am giving two values a and b . a for x-axis b for y-axis. Problem is that when i gave values of a and b . when the difference between a and b is less, then no graph appears
i-e. a= -9 , b= -9 . Otherwise it works
$(function () {
var a, b, x, j;
a = -9;
b = -9;
if (a > b) {
x = a;
j = b
} else {
x = b;
j = a
}
alert("X is " + x);
alert("Y is" + j);
$('#container').highcharts({
chart: {
type: 'bar',
backgroundColor: null
},
credits: {
enabled: false
},
tooltip: {
enabled: false,
},
title: {
text: ''
},
xAxis: {
categories: ["", "", ""],
//minTickInterval:20000,
},
yAxis: {
min: j - (j * 5 / 100),
max: x + (x * 5 / 100),
//min: -50,
//max: -50,
//minTickInterval:20000,
endOnTick: true,
tickPixelInterval: 340,
maxPadding: 0.25,
title: {
text: ''
},
labels: {
formatter: function () {
if (j - (j * 5 / 100) > 1000000) {
return Highcharts.numberFormat((this.value) / 1000000, 0, '', ',') + 'M';
} else if (j - (j * 5 / 100) > 1000) {
return Highcharts.numberFormat((this.value) / 1000, 0, '', ',') + 'K';
} else {
return Highcharts.numberFormat((this.value), 0, '', ',');
}
},
x: 6
}
},
legend: {
backgroundColor: '#FFFFFF',
reversed: true
},
plotOptions: {
series: {
stacking: 'normal'
}
},
series: [{
name: ' ',
data: [a]
},
{
name: ' ',
data: [0, b]
}, ]
});
});
Here's a working fiddle
Just remove:
min: j-(j*5/100),
max: x+(x*5/100)
from the yAxis: { --- some options --- }
Also try this with one value positive and other negative for a and b.
Hope this helps.

Categories

Resources