dimple
万维网使我们可以触手可及的大量数据。 由于这些数据量巨大,因此以突出的方式或以传达您的信息的方式进行显示通常很棘手。 这就是数据可视化的地方。
在本文中,我将指导您使用基于D3.js的dimple.js JavaScript库创建数据可视化,即2015年1月的美国车辆召回。
设定目标
NHTSA / ODI提供了一个召回文件(可通过其网站访问 ),其中包含自1967年以来所有与NHTSA安全相关的缺陷和合规性活动。我们的目标是提取给定月份(2015年1月)的数据,并创建一个条形图。图表,描述制造商召回的车辆总数。
这种数据可视化将不会是解释性的(我们将显示原始数据),也几乎不会是探索性的(观众从该数据中构建出的叙述并不多)。 但是,我确实打算在用户将鼠标悬停在这些条形之一上时在图表旁边显示其他信息。
这就是我们的最终结果:
您可以在文章末尾看到一个(较小的) 实时演示 ,或在CodePen上查看原始演示 。
处理数据
仅保留我们需要的数据
本节中提到的所有文件都可以在我们的GitHub存储库中找到。
原始文件FLAT_RCL.txt
( link )是一个制表符分隔的值文件,其中包含许多数据-准确地为109,682条记录。 有一个随附文件RCL.txt
( 链接 ),该文件详细描述了与此数据有关的列。
由于我们仅对2015年1月的数据(或Record Creation Date
为2015年1月的Record Creation Date
感兴趣,因此可以删除其余记录。 为此,我使用的是OpenOffice Calc电子表格程序(尽管任何其他电子表格软件都足够)。 生成的文件RCL_January_2015.csv
( 链接 )仅计201条记录。
现在,我们需要将列减少为可用列的子集,即:
Record Creation Date
, Maker
, Model
, Model Year
, Begin Date of Manufacturing
End Date of Manufacturing
Potential Number of Units Affected
, Defect Summary
, Consequence Summary
和Corrective Summary
。 然后,我们可以将列名称添加到生成的CSV文件的第一行RCL_January_2015_clean.csv
( 链接 )。
这为我们提供了可视化所需的原始数据。
创建数据结构
现在,我们需要按制造商手动将召回分组,合并那些具有相同缺陷的记录。 我们需要确保合并的记录按日期排序,然后按模型排序,并确保它们具有受影响的累积潜在总数。
我们将使用JSON数据结构进行分组。
为了说明这一点,让我们处理RCL_January_2015_clean.csv
文件的前三个条目。 这些可以分为一行,说明MCI的J4500从2013年,2014年和2015年具有相同的制造年份,也存在相同的缺陷。 受影响的潜在单位数已在数据集中将这三个模型组合在一起。
这是我们将要使用的JSON数据结构:
{
"items": [
{
"item": {
"date": "",
"models": [
""
],
"units": "",
"defect": "",
"consequence": "",
"corrective": ""
}
}
]
}
重复此过程(并转义双引号)之后,我们现在有了CSV文件RCL_January_2015_json.csv ( 链接 )。 为了简洁起见,我们的工作示例将仅显示原始文件的前三名制造者(46个中的3个)。
将数据绑定到D3对象
D3为数据文件格式(例如CSV,TSV或JSON)提供了开箱即用的支持。 执行Ajax调用以获取文件,然后将其解析并转换为JavaScript数组。 我们创建的CSV文件可以通过以下代码获取:
d3.csv("RCL.csv", function (data) {
// process the data
});
我们还可以直接在代码中定义JavaScript数组,我们将在此处出于CodePen演示的目的进行此操作。 数据结构已保持与从CSV文件创建的数组D3尽可能接近。
data = [
{
'Record creation date':'20150105',
'Maker':'MCI',
'Potential number of units affected':'109',
'JSON data': '{
"items":[
{
"item": {
"date":"January, 5 2015",
"models":[
"J4500 (years 2013, 2014, 2015) ..."
],
"units":"109",
"defect":"...",
"consequence":"...",
"corrective":"..."
}
}
]
}'
},
...
];
现在,让我们潜入!
<div id="RecallsChart"></div>
<div id="RecallDetails"></div>
![](https://i-blog.csdnimg.cn/blog_migrate/4bc583ab8b43a9509e1e597f7ed8d11a.png)
免费学习PHP!
全面介绍PHP和MySQL,从而实现服务器端编程的飞跃。
原价$ 11.95 您的完全免费
HTML很简单:两个div,一个用于图表( RecallsChart
),另一个在用户将鼠标悬停在这些条形之一( RecallDetails
)上时显示其他详细信息。
var svg = dimple.newSvg("#RecallsChart", 800, 560);
var myChart = new dimple.chart(svg, data);
myChart.setBounds(60, 30, 710, 355)
我们首先将SVG对象添加到div元素,并通过其ID对其进行引用。 然后,我们将数据链接到将在SVG中呈现的新图表。 最后,我们手动设置图表范围以将其正确放置在其父div内。
var x = myChart.addCategoryAxis("x", "Maker");
x.addOrderRule("Maker");
x.title = '';
我们将图表的x轴设置为数据的“ Maker
字段-我们使用addCategoryAxis
方法,因为制造商构成了分类数据。 我们使用addOrderRule
方法按字母顺序对制造商进行排序,并隐藏x轴标题(应该是制造商),因为制造商的名称不言而喻。
myChart.addLogAxis("y", "Potential number of units affected");
我们将图表的y轴设置为数据的“ Potential Number of Units Affected
的Potential Number of Units Affected
字段。 我们可以在这里使用addMeasureAxis方法 ,该方法根据给定的值定义一个线性轴,但是由于制造商Victory具有的潜在受影响单位数是MCI或Thor的20倍以上,因此所得列将使其他两个相形见war 。 在这种情况下,对数刻度为较小的值提供了更大的空间,因此我们使用addLogAxis
方法,默认为10。
var mySeries = myChart.addSeries(["Maker", "JSON data"], dimple.plot.bar);
现在我们已经定义了轴,可以将它们绑在一起以绘制图形。 为此,我们通过dimple.plot.bar
选择条形图,并将其绑定到Maker
数据字段。 第二个数组元素JSON data
会将JSON data
的JSON部分绑定到每个栏,并允许我们在将鼠标悬停在栏上时访问正确的数据。
mySeries.getTooltipText = function (e) {
var datum = jQuery.parseJSON(e.aggField[1]);
var titles = [];
titles['date'] = 'Record creation date';
titles['units'] = 'Potential number of units affected';
titles['defect'] = 'Defect summary';
titles['consequence'] = 'Consequence summary';
titles['corrective'] = 'Corrective summary';
var html = '';
html += '<span class="maker">'+e.aggField[0]+'</span>';
html += '<br /><br />';
$.each(datum.items, function(index1, element) {
$.each(element, function(index2, item) {
$.each(item, function(key, value) {
if (key === 'models') {
if (value.length == 1) {
html += '<strong>Model</strong>:';
}
else {
html += '<strong>Models</strong>:';
}
html += '<ul>';
$.each(value, function(vk, val) {
html += '<li>'+val+'</li>';
});
html += '</ul>';
}
else {
html += '<em>'+titles[key]+'</em>: '+value+'<br /><br />';
}
});
});
});
$("#RecallDetails").html(html);
return [
"Maker: " + e.aggField[0],
"Potential number of units affected: " +
parseInt(e.cy).toLocaleString('en')
];
};
默认情况下,将鼠标悬停在绘图单位(此处为条形)上时会显示工具提示,并显示轴和系列数据。 在我们的示例中:制造商(x轴值),受影响的潜在单位数(y轴值)以及JSON data
的纯文本值。
getTooltipText
函数在此处已重载,以处理JSON数据并将其显示在侧面的另一个div中。 它返回一个我们要显示为工具提示的数据数组,即制造商的名称(数据行的第一个汇总字段)和受影响的单位数(我们从y轴获取并本地化为通过内置的toLocaleString
JavaScript方法生成的通用英文数字格式)。
但是,让我们回到JSON数据解析。
我们正在访问的两个聚合字段( aggField[0]
和aggField[1]
)与我们之前设置为系列( ["Maker", "JSON data"]
)的数据字段数组匹配,而aggField
本身是基础属性元素对象。
我们使用jQuery的parseJSON
函数解析JSON字符串,设置一个与我们的JSON对象的键匹配的全长标题数组,然后通过遍历JSON对象,我们构建一个HTML字符串以添加ID为RecallDetails
的div。
myChart.ease = "elastic";
myChart.draw(1000);
最终,我们使用具有一秒钟延迟的弹性缓和来进行美学过渡。
x.shapes.selectAll("text")
.style("text-anchor", "end")
.each(function () {
var rec = this.getBBox();
d3.select(this)
.attr("transform", "rotate(-90," + (rec.x + rec.width) + "," + (rec.y + (rec.height / 2)) + ") translate(5, 0)");
});
我终于说了吗? 好吧,这里我们在x轴标签上添加了另一个美学技巧。
默认情况下,x轴标签是水平书写的。 但是它们很容易重叠,因此我们将垂直编写它们。 这是dimple对其底层D3对象进行曝光的地方。 请注意,我们只能在绘制图表后myChart.draw()
即在myChart.draw()
调用之后)进行myChart.draw()
。
为此,我们首先选择每个标签文本,或者选择链接到每个标签x轴的匹配SVG形状。 getBBox()
方法属于InterfaceSVGLocatable,并返回定义边框的SVGRect对象,该对象显示其坐标,高度和宽度。 然后,我们旋转SVG框,并进行轻微的垂直平移以使其更靠近x轴线。
这是最终结果:
请参阅CodePen上SitePoint ( @SitePoint )在2015年1月进行的Pen Vehicles召回 。
该笔的宽度已减小,以使其适合物品。 您可以在这里看到原始的CodePen
结论
在本文中,我们看到了如何清理和准备数据以进行数据可视化,特别是定义了一个数据结构以匹配我们所想到的最终结果。 我们同时使用了dimple.js和D3.js库,并对jQuery进行了一些有限的调用(主要与JSON处理有关)。 我们通过重载dimple的工具提示功能从数据中绘制了条形图,并进行了一些探索性的交互。 我们还访问了基础D3对象来操纵x轴标签。
附带说明一下,SVG现在得到了广泛的支持 ,但是最好事先进行检查(例如,使用Modernizr ),并在需要时提供备用(例如PNG图像)。 当然,还应考虑D3.js和dimple.js的条件加载。
如果您想更深入地研究数据可视化,Udacity提供了一个自定进度的MOOC,标题为“ 数据可视化和D3.js” ,其中涵盖了可视化概念,D3.js和dimple.js的使用,叙述结构和动画。 另外,如果您想了解该库背后的概念, Mike Bostock的站点 (D3.js的创建者)是一个理想的来源,而dimple和D3都提供了一些示例供您学习。
翻译自: https://www.sitepoint.com/create-data-visualizations-javascript-dimple-d3/
dimple