일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- SQL0104
- 생산SCM
- 시큐어코딩
- adobe flash 보안정책
- Token ) was not valid
- D3.js
- SEcure coding
- flash에러
- rmate chart flash
- 유효재고
- 로트관리
- D3차트
- mms.cfg
- chart flash
- rmate chart
- Today
- Total
티스토리 뷰
이번 장에서는 여러 데이터를 표현하는 기본적인 차트 중
다중곡선 차트에 대해 구성해본다.
그 중 예시로 연간 전기사용량(Electricity. kWh)에 대해서
차트를 구성해본다.
[JSP]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | <!DOCTYPE html> <meta charset="utf-8"> <style> .axis--x path { display: none; } .line { fill: none; stroke: steelblue; stroke-width: 1.5px; } </style> <svg width="960" height="500"></svg> <script src="//d3js.org/d3.v4.min.js"></script> <script> var svg = d3.select("svg"), margin = {top: 20, right: 80, bottom: 30, left: 50}, width = svg.attr("width") - margin.left - margin.right, height = svg.attr("height") - margin.top - margin.bottom, g = svg.append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); var parseTime = d3.timeParse("%Y%m%d"); var x = d3.scaleTime().range([0, width]), y = d3.scaleLinear().range([height, 0]), z = d3.scaleOrdinal(d3.schemeCategory10); var line = d3.line() .curve(d3.curveBasis) .x(function(d) { return x(d.date); }) .y(function(d) { return y(d.electricity); }); d3.tsv("./js/02_data1.tsv", type, function(error, data) { if (error) throw error; var device = data.columns.slice(1).map(function(id) { return { id: id, values: data.map(function(d) { return {date: d.date, electricity: d[id]}; }) }; }); x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(device, function(c) { return d3.min(c.values, function(d) { return d.electricity; }); }), d3.max(device, function(c) { return d3.max(c.values, function(d) { return d.electricity; }); }) ]); z.domain(device.map(function(c) { return c.id; })); g.append("g") .attr("class", "axis axis--x") .attr("transform", "translate(0," + height + ")") .call(d3.axisBottom(x)); g.append("g") .attr("class", "axis axis--y") .call(d3.axisLeft(y)) .append("text") .attr("transform", "rotate(-90)") .attr("y", 6) .attr("dy", "0.71em") .attr("fill", "#000") .text("Electricity, kWh"); var etc = g.selectAll(".etc") .data(device) .enter().append("g") .attr("class", "etc"); etc.append("path") .attr("class", "line") .attr("d", function(d) { return line(d.values); }) .style("stroke", function(d) { return z(d.id); }); etc.append("text") .datum(function(d) { return {id: d.id, value: d.values[d.values.length - 1]}; }) .attr("transform", function(d) { return "translate(" + x(d.value.date) + "," + y(d.value.electricity) + ")"; }) .attr("x", 3) .attr("dy", "0.35em") .style("font", "10px sans-serif") .text(function(d) { return d.id; }); }); function type(d, _, columns) { d.date = parseTime(d.date); for (var i = 1, n = columns.length, c; i < n; ++i) d[c = columns[i]] = +d[c]; return d; } </script> |
[.TSV]
[line 20 ~ 25]
d3.select로 svg(id 값)를 선택하고
그 밑에 margin과 width, height을 설정한다.
지금까지 여러차트를 만들면서 봤겠지만,
width와 height의 설정값이 대부분 비슷한 것을 알 수 있다.
margin의 크기를 상수로 정해주고, 그 크기만큼 svg의 크기에서 빼줌으로써
차트의 실질적인 가로크기와 세로크기를 지정해주기 때문.
다음은 'g' 요소로 svg를 그룹화한다.
사실 'g'는 위에서 지정한 svg 변수에 추가하여 svg를 그룹화 할 때 사용하므로
d3보다는 svg쪽에 가깝다.
[line 27] parseTime부분의 파싱에 대한 설명은
전 장 예제에서 충분히 설명하였고,
[line 29 ~ 31]을 보면
기존 x축과 y축은
어떤 단위로 어디까지(크기) 표현할 것인지를 각각 변수에 설정하는 것이고,
그리고 처음 보는 z축은
데이터 시각화에 있어서 중요한 부분이다.
바로, 자동으로 각 선의 옵션을 설정해주는 것.
해당 옵션의 함수는 d3.schemeCategory10으로 하고
이 함수 카테고리에 대한 설명도 많이 다뤘으므로 패스.
[line 33 ~ 36]
d3.line 라인속성 설정과
curve의 부드러운선이 아닌 곡선이며,
x와 y에 대한 function은
그래프에 그려질 데이터를 설정하는 것이며
d는 enter()로 넣어진 데이터이고,
이는 데이터에 접근하기 위해서 콜백함수로 d를 다룹니다.
[line 38 ~ 48]
이미 tsv에 대한 자세한설명은
전 장에서 예제를 다루며 했었지만
다시한번 복습차원에서 차근차근 해석해본다.
38 39 40 41 42 43 44 45 46 47 48 | d3.tsv("./js/02_data1.tsv", type, function(error, data) { if (error) throw error; var device = data.columns.slice(1).map(function(id) { return { id: id, values: data.map(function(d) { return {date: d.date, electricity: d[id]}; }) }; }); |
d3.tsv는 tsv파일을 가져오는 명령어의 d3함수이며
뒤의 "./js/02_data1.tsv"는 실제로 PC에 저장되어있는 파일명이며
현재 소스코드로부터 해당 파일의 경로를 나타낸 것입니다.
type의 설명은 전 장에 설명해서 넘어가고,
error(에러)와 data(tsv파일)는 해당 요소들을 다루기 위한 콜백함수다.
그리고 처음보는 함수인
data.columns.slice(1)는
컬럼(columns)의 데이터를 쌓는 역할을 한다.
slice(1)는 첫번째 데이터는 빼고 그 다음 데이터부터 쌓는 것을 의미한다.
따라서 date 부분인 날짜컬럼 영역 부분은 맵핑 되지 않고
다음 컬럼부터 맵핑된다.
아래 URL를 보면 이해하는데 도움이 된다.
Description reference to slice URL :
https://developer.mozilla.org/JavaScript/Reference/Array/slice
[line 50 ~ 55]
50 51 52 53 54 55 | x.domain(d3.extent(data, function(d) { return d.date; })); y.domain([ d3.min(device, function(c) { return d3.min(c.values, function(d) { return d.electricity; }); }), d3.max(device, function(c) { return d3.max(c.values, function(d) { return d.electricity; }); }) ]); z.domain(device.map(function(c) { return c.id; })); |
아까 크기를 지정해준 x와 y를 직접 축으로 그려줍니다.
d3.extent는 데이터 중에서 최대 값과 최소 값을 찾아서 그 값으로 x축을 그려줍니다.
반면 y는 d3.min과 d3.max로 y축의 최소, 최대값을 찾아 일일이 지정해 줍니다.
그리고 z는 데이터들의 index(id)별로 전에 설정한 옵션(d3.schemeCategory10)을 매핑시켜줍니다.
[line 83]
데이터를 묶어주는 것은 datum과 data가 있는데,
그 중 datum은 정적 데이터(업데이트가 없는)를 묶어주는 메소드입니다.
해당 영역(etc.append("text"))안에 든 데이터들을 id와 value에 묶어주는 역할을 합니다.
그리고 데이터를 좌표에 나타내기 위해 변형(transform)시킵니다.
x{d(데이터).value(매핑 시킨 data).date(그 중 날짜)}, y{d.value.electricity(해당 값)}으로
즉, ( x , y ) 모양으로 바꿔준 것.
다음은 tsv파일에 데이터를 더 추가해서 실행시켜본다.
데이터는 정해진 데이터가 없고
임의의 데이터인 난수이기 때문에
난수 입력 데이터는 엑셀로 작업하면 쉽게 적용시킬 수 있다.
=ROUND(RAND()*(M-N)+N,P)
* M : 발생시키고자 하는 범위의 가장 큰 수
* N : 발생시키고자 하는 가장 작은 수
* P : 소수점 아래 자리 수
ex) = ROUND(RAND()*(45-20)+20,1)
20 에서 45사이의 난수로서 소수점 아래 1자리까지 표시
(20 과 45을 포함한 난수 발생)
'D3.js' 카테고리의 다른 글
D3.js V4 (0) | 2018.08.10 |
---|---|
12 Real-Time Transition (2) | 2018.07.20 |
10 CSV(외부파일)로 차트(Chart) 구현 (0) | 2018.06.25 |
09 TSV(외부파일)로 차트(Bar Chart) 구현 (1) | 2018.06.21 |
07 원형 차트(Pie & Doughnut Chart) (1) | 2018.06.15 |