使用Dimple和D3在JavaScript中创建数据可视化
万维网将大量的数据放在我们的指尖。由于这些数据的庞大量,以一种突出的方式来呈现它,或者以一种让你的信息被理解的方式,通常会被证明是棘手的。这就是数据可视化的用武之地。
在本文中,我将指导您创建一个数据可视化,即2015年1月的美国汽车召回,使用dimple.jsJavaScript库构建在D3.js.
设定目标
的国家公路交通安全管理局/海外开发提供一个召回文件(可通过他们的网站),包括自1967年以来所有与NHTSA安全相关的缺陷和合规活动。我们的目标是提取给定月份(2015年1月)的数据,并从中创建一个柱状图,描述制造商的车辆召回总数。
这个数据可视化将不是解释性的(我们将展示原始数据),也几乎不是探索性的(从这些数据中没有太多的叙述供观众构建)。然而,当用户将鼠标悬停在其中一个柱上时,我打算在图表旁边显示额外的信息。
这就是我们最终得到的结果:
你可以看到一个(较小的)现场演示在文章的结尾还是在CodePen上查看原文.
使用数据
只保留我们需要的数据
本节中提到的所有文件都可以在我们的GitHub回购.
原始文件FLAT_RCL.txt
(链接)是一个以制表符分隔的值文件,其中包含很多确切地说,是109,682条记录。有一个附带的文件RCL.txt
(链接),详细列出与该数据相关的列。
因为我们只对2015年1月的数据感兴趣,或者更确切地说,是2015年1月的记录记录创建日期
2015年1月-其余的记录可以删除。要做到这一点,我使用OpenOffice Calc电子表格程序(尽管任何其他电子表格软件就足够了)。生成的文件,RCL_January_2015.csv
(链接)只有201条记录。
现在我们需要将列缩减为可用列的子集,即:记录创建日期
,制造商
,模型
,模型一年
,开始生产日期
,生产结束日期
,受影响的潜在单元数
,缺陷的总结
,结果总结
,纠正总结
.然后,我们可以将列名添加到生成的CSV文件的第一行,RCL_January_2015_clean.csv
(链接).
这为我们提供了可视化所需的原始数据。
创建数据结构
现在我们需要根据制造商手动对召回进行分组,合并具有相同缺陷的记录。我们需要确保组合的记录是按日期排序的,然后是按模型排序的,并且它们具有受影响的累积潜在的单元总数。
我们将使用JSON数据结构进行分组。
为了说明这一点,让我们处理的前三个条目RCL_January_2015_clean.csv
文件。这些可以归为一行,说明MCI的J4500来自2013年、2014年和2015年,它们的制造年份相同,存在相同的缺陷。受影响的单元的潜在数量已经在数据集中将这三个模型组合在一起。
下面是我们将要使用的JSON数据结构:
{“项目”:[{“项目”:{“日期”:"",“模型”:[""],“单位”:"",“缺陷”:"",“结果”:"",“纠正”:""}}]}
在迭代这个过程之后(并转义双引号),我们现在有了CSV文件RCL_January_2015_json.csv(链接).为简洁起见,我们的工作示例将只显示原始文件的前三个制作者(46个中的3个)。
将数据绑定到D3对象
D3为数据文件格式(如CSV、TSV或JSON)提供了开箱即用的支持。执行Ajax调用来获取文件,然后解析该文件并将其转换为JavaScript数组。我们创建的CSV文件可以用下面的代码获取:
d3.csv(“RCL.csv”,函数(数据){//处理数据});
我们还可以在代码中直接定义JavaScript数组,为了实现CodePen演示的目的,我们将在这里这样做。数据结构尽可能接近D3从CSV文件中创建的数组。
数据=[{“记录创建日期”:“20150105”,“制造商”:MCI的,“可能受影响的单位数目”:“109”,“JSON数据”:'{“项目”:[{“项目”:{“日期”:“2015年1月5日”,“模型”:[“J4500(2013年、2014年、2015年)……”],“单位”:“109”,“缺陷”:“…”,“结果”:“…”,“纠正”:“…”}}]}'},...];
现在,让我们潜入!
<divid="RecallsChart">div><divid="RecallDetails">div>
HTML很简单:两个div,一个用于图表(RecallsChart
),另一个显示更多的细节,如果用户将鼠标悬停在其中一个栏上(RecallDetails
).
varsvg=酒窝.newSvg(“# RecallsChart”,800,560);varmyChart=新酒窝.图表(svg,数据);myChart.setBounds(60,30.,710,355)
我们首先向div元素添加一个SVG对象,通过它的id引用它。然后我们将数据链接到新图表,该图表将在SVG中呈现。最后,我们手动设置图表边界,以在其父div中正确定位它。
varx=myChart.addCategoryAxis(“x”,“制造商”);x.addOrderRule(“制造商”);x.标题=”;
我们将图表的x轴设为制造商
字段的数据,我们使用addCategoryAxis
方法作为创客构成的分类数据。我们用字母顺序给制造商排序addOrderRule
方法并隐藏x轴标题(可能是生成器),因为生成器名称是不言自明的。
myChart.addLogAxis(“y”,“可能受影响的单位数目”);
我们将图表的y轴设为受影响的潜在单元数
字段的数据。我们可以用addMeasureAxis方法在这里,它定义了给定值的线性轴,但由于制造商Victory的潜在受影响单位数量是MCI或Thor的20倍以上,因此产生的列将使其他两者相形见绌。在这种情况下,对数刻度为较小的值提供了更多的空间,因此我们使用addLogAxis
方法,该方法默认以10为基数。
varmySeries=myChart.addSeries([“制造商”,“JSON数据”],酒窝.情节.酒吧);
现在我们已经定义了坐标轴,我们可以将它们连接在一起以呈现图形。为此,我们选择一个柱状图通过dimple.plot.bar
,我们把它绑在制造商
数据字段。第二个数组元素,JSON数据
,将我们数据的JSON部分绑定到每个栏,使我们能够访问正确的数据时,鼠标悬停在栏上。
mySeries.getTooltipText=函数(e){var基准=jQuery.parseJSON(e.aggField[1]);var标题=[];标题[“日期”]=“记录创建日期”;标题[“单位”]=“可能受影响的单位数目”;标题[“缺陷”]=“缺陷总结”;标题[“结果”]=“结果总结”;标题[“纠正”]=“纠正总结”;var超文本标记语言=”;超文本标记语言+ =' < span class = "制造商" >+e.aggField[0]+“< / span >”;超文本标记语言+ ='
';$.每一个(基准.项目,函数(index1,元素){$.每一个(元素,函数(index2,项){$.每一个(项,函数(关键,价值){如果(关键= = =“模型”){如果(价值.长度= =1){超文本标记语言+ =' <强>模型< / >强:“;}其他的{超文本标记语言+ =' <强> < /模型强>:“;}超文本标记语言+ =' < ul > ';$.每一个(价值,函数(vk,瓦尔){超文本标记语言+ =<李>的+瓦尔+“李< / >”;});超文本标记语言+ =“< / ul >”;}其他的{超文本标记语言+ =' < em > '+标题[关键]+”< / em >:“+价值+'
';}});});});$(“# RecallDetails”).超文本标记语言(超文本标记语言);返回[制造商:“+e.aggField[0],“可能受影响的单位数目:”+方法用于(e.cy).toLocaleString(“en”)];};
默认情况下,当鼠标悬停在一个绘图单元(这里是条)上时,将显示工具提示,并显示轴和系列数据。在我们的例子中:制造商(x轴值),受影响的潜在单元数(y轴值),以及我们的纯文本值JSON数据
.
的getTooltipText
函数在这里重载,以处理JSON数据并将其显示在另一个div中。它返回我们想要作为工具提示显示的数据数组,即制造商的名称(数据线的第一个聚合字段)和受影响的单元数(我们从y轴获得,并通过内置函数将其本地化为通用的英文数字格式)toLocaleString
JavaScript方法)。
但是让我们回到JSON数据解析。
我们正在访问的两个聚合字段(aggField [0]
而且aggField [1]
)匹配之前设置为series (["Maker", "JSON数据"]
),aggField
本身是基础元素对象的属性。
我们用jQuery解析JSON字符串parseJSON
函数,设置一个与JSON对象的键匹配的完整长度标题数组,然后,通过迭代JSON对象,我们构建一个HTML字符串,并使用id添加到div中RecallDetails
.
myChart.缓解=“弹性”;myChart.画(1000);
我们最终用一秒延迟的弹性轻松绘制了具有美学过渡的图表。
x.形状.selectAll(“文本”).风格(“文本链接”,“结束”).每一个(函数(){var矩形=这.getBBox();d3.选择(这).attr(“转换”,“旋转(-90年,“+(矩形.x+矩形.宽度)+”、“+(矩形.y+(矩形.高度/2))+")翻译(5,0)");});
我说最后了吗?在这里,我们在x轴标签上添加了另一个美学技巧。
默认情况下,x轴标签是水平书写的。但是它们很容易重叠,所以我们把它们竖着写。这就是dimple暴露其底层D3对象的方便之处。请注意,我们只能在图表绘制完成后更改它,因此在myChart.draw ()
调用。
为此,我们首先选择每个标签文本,或者更确切地说是与每个标签的x轴链接的匹配SVG形状。的getBBox ()
方法属于InterfaceSVGLocatable并返回一个SVGRect对象,该对象定义了边界框,暴露了它的坐标、高度和宽度。然后,我们对SVG框进行旋转,并进行轻微的垂直平移,使其更接近x轴线。
这是最终结果:
看钢笔2015年1月车辆召回由Si必威西盟体育网页登录tePoint (@必威西盟体育网页登录SitePoint)CodePen.
这支笔的宽度被缩小了,以便能塞进这篇文章里。你可以看到原始的CodePen在这里
结论
在本文中,我们了解了如何为数据可视化清理和准备数据,具体定义一个数据结构来匹配我们心目中的最终结果。我们同时使用dimple.js和D3.js库,对jQuery进行了一些有限的调用(主要与JSON处理有关)。我们从我们的数据中绘制了条形图,通过重载dimple的工具提示功能进行了一些探索性的交互。我们还访问了底层的D3对象来操作x轴标签。
顺便说一句,SVG现在是广泛的支持,但最好事先检查一下Modernizr例如),并在任何需要的地方提供一个备份,例如PNG图像。当然,D3.js和dimple.js的条件加载也要考虑在内。
如果你想深入研究数据可视化,Udacity提供了一个名为数据可视化和D3.js包括可视化概念,D3.js和dimple.js的使用,叙事结构和动画。同时,Mike Bostock的网站如果你想了解这个库背后的概念,(D3.js的创造者)是完美的来源酒窝而且D3提供一个可供学习的例子列表。