超时代无可比拟的数据可视化工具--TZLEAU
2019-05-28 13:25
309 查看
小编的团队最近参加了天池上的一个新人赛–城市计算AI挑战赛,该比赛是对杭州地铁的未来某日客流量进行预测,训练数据集包含了25天的地铁刷卡数据。
在对数据清洗筛选时,我们一开始使用了Tableau进行可视化制图,但是由于Tableau不支持十分钟间隔划分数据并且操作繁琐,所以我们萌生了一个想法——自己写一个可视化工具,并将它开源了出来,欢迎大家交流!
此可视化工具我们使用JavaScript编写,使用浏览器就能很方便的制图及下载,先来看一下界面吧!
是不是很简洁呀!上传要进行制图的文件(.csv)即可快速制图,速度比python快了不少呢!
以上是示例图,通过这些图我们可以很方便的分析出:哪一个地铁站属于商务区/居民区,杭州东站的客流量有“潮汐特征”等等,大家也可以根据自己的需要对代码进行小幅度修改以制出自己想要的可视化图像。下面就是开源代码:
<html> <meta charset="utf-8"/> <head> <script type="text/javascript"> function parseTime(ts) { ts = ts.replace(/-/g,':').replace(' ', ':') let tss = ts.split(':') return new Date(tss[0],(tss[1]-1),tss[2],tss[3],tss[4],tss[5]) } function createRecordByString(string) { let commaSepStr = string.split(',') if (commaSepStr[0] == 'time') { return null } let ret = new Object() let time = parseTime(commaSepStr[0]) ret.timeByMins = time.getHours() * 60 + time.getMinutes() ret.stationId = commaSepStr[1] if (commaSepStr[2] == "0") { ret.status = "in" } else { ret.status = "out" } return ret } function recordsToSections(records) { var sectionsList = [] for (var i = 0; i < 81; i++) { sectionsList.push([]) } var recordidx = 0 for (var secid = 0; secid < 6 * 24; ++secid) { for (let sections of sectionsList) { sections.push([0, 0]) } for (true ; records[recordidx] != undefined && (records[recordidx].timeByMins < secid * 10) && (recordidx < records.length); ++recordidx) { var sectionsListIdx = parseInt(records[recordidx].stationId) if (records[recordidx].status == "in") { sectionsList[sectionsListIdx][secid][0]++ } else { sectionsList[sectionsListIdx][secid][1]++ } } } return sectionsList } function maxOfSectionArr(sections) { var ret = 0 for (let [xin, xout] of sections) { if (xin > ret) { ret = xin } if (xout > ret) { ret = xout } } return ret } function maxOfSectionIns(sections) { var ret = 0 for (let [xin, _] of sections) { if (xin > ret) { ret = xin } } return ret } function maxOfSectionOuts(sections) { var ret = 0 for (let [_, xout] of sections) { if (xout > ret) { ret = xout } } return ret } function paintSections(canvas, sections) { let yMax = Math.ceil(maxOfSectionArr(sections) * 1.11) let cw = canvas.width let ch = canvas.height let cmid = ch / 2 let dw = cw / (sections.length + 10) let dh = cmid / yMax let context = canvas.getContext('2d') context.fillStyle = "#FFFFFF" context.fillRect(0, 0, cw, ch) context.fillStyle = "#000000" context.fillRect(dw * 5, ch - 10, dw * 144, 1) for (var i = 0; i <= sections.length / 6; i++) { context.fillStyle = "#AAAAAA" context.fillRect(dw * (i * 6 + 5), 13, 1, ch - 26) context.fillStyle = "#000000" context.fillRect(dw * (i * 6 + 5), ch - 13, 1, 3) context.fillText(i.toString(), dw * (i * 6 + 5), 13) } context.fillStyle = "#7F7F7F" let inMax = maxOfSectionIns(sections) context.fillRect(dw * 5, cmid - inMax * dh, dw * 144, 1) let outMax = maxOfSectionOuts(sections) context.fillRect(dw * 5, cmid + outMax * dh, dw * 144, 1) context.fillStyle = "#000000" context.fillText("outMax=" + inMax.toString(), dw * 5, cmid - inMax * dh) context.fillText("inMax=" + outMax.toString(), dw * 5, cmid + outMax * dh) context.moveTo((i + 4) * dw, cmid) context.beginPath() context.strokeStyle = "#FF7700" for (var i = 0; i < sections.length; i++) { let [xin, _] = sections[i] context.lineTo((i + 5) * dw, cmid - xin * dh) } context.stroke() context.moveTo((i + 4) * dw, cmid) context.beginPath() context.strokeStyle = "#0077FF" for (var i = 0; i < sections.length; i++) { let [_, xout] = sections[i] context.lineTo((i + 5) * dw, cmid + xout * dh) } context.stroke() } function main() { document.getElementById('fileinput').addEventListener('change', onfilechange) } function onfilechange(event) { let fileSelected = document.getElementById('fileinput').files[0] var fr = new FileReader() fr.onload = function() { let values = this.result.split('\n') solveData(values) } fr.readAsText(fileSelected) updateStatBar("reading data") } function solveData(values) { updateStatBar("cleaning") canvasContainer = document.getElementById("tzleau") canvasContainer.innerHTML = "" linkContainer = document.getElementById("downloader") linkContainer.innerHTML = "" updateStatBar("parsing records") var records = [] for (let valueLine of values) { record = createRecordByString(valueLine) if (record == null) { continue } records.push(record) } updateStatBar("combining records") sectionsList = recordsToSections(records) updateStatBar("painting") for (var i = 0; i < sectionsList.length; i++) { var canvas = document.createElement("canvas") canvas.id = "tzleaucanvas" + i.toString() canvas.width = 500 canvas.height = 500 canvas.style = "border: 1px solid black" canvasContainer.appendChild(canvas) paintSections(canvas, sectionsList[i]) var imageLink = canvas.toDataURL("image/png") var dldlink = document.createElement("a") dldlink.id = "tzleauimg" + i.toString() dldlink.href = imageLink dldlink.alt = "tzleauimg" + i.toString() + " image" dldlink.download = "tzleauimg" + i.toString() + ".png" dldlink.innerHTML = "image" + i.toString() + "<br/>" linkContainer.appendChild(dldlink) } updateStatBar("ready") } function updateStatBar(newText) { document.getElementById("statbar").innerText = newText } </script> </head> <body onload="main()"> <input type="file" id="fileinput"/> <div id="tzleau"> 所有图像会显示在这里 </div> <hr/> <div id="downloader"> 下载链接会显示在这里 </div> <hr/> <div id="statbar">ready</div> </body> <ml>
欢迎大家Star以及fork!
相关文章推荐
- 初始数据可视化工具ECharts
- 39个大数据可视化工具 数据研究必备
- 可视化管理mysql数据工具Navicat
- 一共56个,盘点最实用的大数据可视化分析工具
- 前端数据可视化工具库
- Csimsoft.Bolt.v1.0.0.X64 螺栓设计 + CEETRON.GLView.Inova.v10.0.0.Win32 64 linux 数据三维可视化工具
- 20个数据可视化工具点评
- 盘点56个最实用的大数据可视化分析工具
- 大数据可视化——这些必须知道的工具!
- 数据可视化工具
- 免费才是王道:盘点开发者须知的25个免费数据可视化工具
- Vega数据可视化工具——教你轻松玩转大数据可视化 | 附代码
- SegY地震体数据可视化分析工具 开发笔记 5 数据切割和抽取
- 二十大数据可视化工具点评
- 最好用的20个数据可视化工具(二)
- 最实用的5款数据可视化工具,教你玩转图表报表
- 免费才是王道:盘点开发者须知的25个免费数据可视化工具
- 开源数据可视化工具(For Apache Kylin)使用说明
- 30 个最好的数据可视化工具推荐
- 15个最有用的数据可视化工具