開発環境
- OS X El Capitan - Apple (OS)
- Emacs (Text Editor)
- JavaScript (プログラミング言語)
- D3.js (JavaScript Library)
- Safari(Web browser)
- JavaScript 第6版 (David Flanagan(著)、村上 列(翻訳)、オライリージャパン)(参考書籍)
- インタラクティブ・データビジュアライゼーション(Scott Murray(著)、長尾 高弘(翻訳)、オライリージャパン)(参考書籍)
Pythonからはじめる数学入門 (Amit Saha (著)、黒川 利明 (翻訳)、オライリージャパン)の3章(データを統計量で記述する)、3.9(プログラミングチャレンジ)、問題3-1(よりよい相関関係を求めるプログラム)をJavaScript(とD3.js)で取り組んでみる。(バージョンアップで D3.js にいろいろ変更点があったみたい。)
問題3-1(よりよい相関関係を求めるプログラム)
コード(Emacs)
HTML5
<div id="graphs0"></div>
<button id="calc_and_draw">calc and draw</button>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.min.js"></script>
<script src="sample1.js"></script>
JavaScript
(function () {
'use strict';
var x0,
x1,
x2,
y0,
y1,
y2,
setNumbers,
sum,
findCorrXandY,
width = 600,
height = 400,
padding = 50,
padding_left = 50,
div_graphs = document.querySelector('#graphs0'),
input_number = document.querySelector('#number0'),
button_calc_and_draw = document.querySelector('#calc_and_draw'),
drawGraph,
drawGraphs;
sum = function (numbers) {
var i,
max,
result = 0;
for (i = 0, max = numbers.length; i < max; i += 1) {
result += numbers[i];
}
return result;
};
setNumbers = function () {
var i,
max;
x0 = [];
x1 = [];
x2 = [];
y0 = [];
y1 = [];
y2 = [];
for (i = 0; i < 10; i += 1) {
x0[i] = i;
x1[i] = Math.floor(Math.random() * 10);
y0[i] = 9 - i;
y1[i] = Math.floor(Math.random() * 10);
}
for (i = 0; i < 11; i += 1) {
x2[i] = Math.floor(Math.random() * 10);
y2[i] = Math.floor(Math.random() * 10);
}
};
findCorrXandY = function (x, y) {
var x_len = x.length,
y_len = y.length,
n,
prod = [],
sum_prod_x_y,
sum_x,
sum_y,
squared_sum_x,
squared_sum_y,
x_square_sum,
y_square_sum,
numerator,
denominator_term_x,
denominator_term_y,
denominator,
i;
if (x_len !== y_len) {
throw {
name: 'findCorrXandY Error',
message: '2つの数集合の長さが異なり、相関関数は計算できない'
};
}
n = x_len;
for (i = 0; i < n; i += 1) {
prod[i] = x[i] * y[i];
}
sum_prod_x_y = sum(prod);
sum_x = sum(x);
sum_y = sum(y);
squared_sum_x = Math.pow(sum_x, 2);
squared_sum_y = Math.pow(sum_y, 2);
x_square_sum = sum(
x.map(function (xi) {
return Math.pow(xi, 2);
})
);
y_square_sum = sum(
y.map(function (yi) {
return Math.pow(yi, 2);
})
);
numerator = n * sum_prod_x_y - sum_x * sum_y;
denominator_term_x = n * x_square_sum - squared_sum_x;
denominator_term_y = n * y_square_sum - squared_sum_y;
denominator = Math.sqrt(denominator_term_x * denominator_term_y);
return numerator / denominator;
};
drawGraph = function (x, y, id_str) {
var n = x.length,
y0 = x.concat(y),
svg,
xscale,
xaxis,
yscale,
yaxis;
xscale = d3.scaleLinear()
.domain([0, n])
.range([padding_left, width - padding]);
xaxis = d3.axisBottom().scale(xscale);
yscale = d3.scaleLinear()
.domain([d3.min(y0), d3.max(y0)])
.range([height - padding, padding]);
yaxis = d3.axisLeft().scale(yscale);
svg = d3.select('#' + id_str)
.append('svg')
.attr('width', width)
.attr('height', height);
console.log(y0);
svg.selectAll('line')
.data(y0)
.enter()
.append('line')
.attr('x1', function (d, i) {
if (i < (n - 1)) {
return xscale(i);
}
if (i === n - 1 || i === 2 * n - 1) {
return xscale(0);
}
if (i < (2 * n - 1)) {
return xscale(i - n);
}
})
.attr('y1', function (d, i) {
if (i < (n - 1)) {
return yscale(d);
}
if (i === (n - 1) || i === (2 * n - 1)) {
return yscale(0);
}
if (i < (2 * n - 1)) {
return yscale(d);
}
})
.attr('x2', function (d, i) {
if (i < (n - 1)) {
return xscale(i + 1);
}
if (i === (n - 1) || i === (2 * n - 1)) {
return xscale(0);
}
if (i < (2 * n - 1)) {
return xscale(i - n + 1);
}
})
.attr('y2', function (d, i) {
if (i < (n - 1)) {
return yscale(y0[i + 1]);
}
if (i === (n - 1) || i === (2 * n - 1)) {
return yscale(0);
}
if (i < (2 * n - 1)) {
return yscale(y0[i + 1]);
}
})
.attr('stroke', function (d, i) {
if (i < (n - 1)) {
return 'green';
}
if (i === (n - 1) || i === (2 * n - 1)) {
return 'white';
}
if (i < (2 * n - 1)) {
return 'blue';
}
});
svg.append('g')
.attr('transform', 'translate(0, ' + (height - padding) + ')')
.call(xaxis);
svg.append('g')
.attr('transform', 'translate(' + padding_left + ', 0)')
.call(yaxis);
};
drawGraphs = function () {
setNumbers();
div_graphs.innerHTML =
'x: <span style="color:green">----------</span> ' +
'y: <span style="color:blue">----------</span></br><br>';
[x0, y0, x1, x2].forEach(function (x, i) {
[y0, x0, y1, y2].forEach(function (y, j) {
var correlation,
id_str;
div_graphs.innerHTML +=
'x: ' + x.join(', ') + '<br>' +
'y: ' + y.join(', ') + '<br>';
try {
correlation = findCorrXandY(x, y);
id_str = 'graph' + i.toString() + j.toString();
div_graphs.innerHTML +=
'相関係数: ' + correlation + '<br>' +
'<div id="' + id_str + '"><div>';
drawGraph(x, y, id_str);
} catch (e) {
div_graphs.innerHTML += e.name + ': ' + e.message + '<br>';
} finally {
div_graphs.innerHTML += '<br>';
}
});
});
};
button_calc_and_draw.onclick = drawGraphs;
drawGraphs();
}());
0 コメント:
コメントを投稿