为了创建有意义的数据可视化表示形式以及用于分析所述数据的免费工具,拥有一个精心设计的数据管理框架非常重要。 这需要正确的后端存储,用于数据访问的范例以及用于表示和分析的引人入胜的前端。 您可以使用多种工具在Web应用程序中构建数据访问堆栈,我们将在此处进行探索。
如果您正在收集与您的访客相关的数据,他们将需要某种方式来使用它。 我们的责任是为访客提供透明度,为他们提供最佳体验,并建立直观,高效的工具以使他们能够获得这些见解。 该数据的视觉表示只是其中一部分。 我们用来存储,转换和传输数据的机制是提供这些丰富体验的重要组成部分。
数据存储选项
近年来,数据存储已成为一个巨大的市场。 确定要为应用程序使用哪种技术可能是一项艰巨的任务。 需要考虑以下几件事:性能,可伸缩性,易于实施以及您和您的团队的特定技能。 最后一点非常重要,经常被忽略。 如果您的团队中有一组SQL开发人员,则必须说服迁移到MongoDB实现的好处,才能说服您走这条路。
除了“坚持您所知道的”之外,您没有应该使用的快速简便的答案。 平面数据集可以相对容易地使用。 它们被构造为单个表(请考虑CSV文件),并且相对容易理解。 这些资源的局限性很快就会显示出来,因为它们随着增长而表现不佳,并且难以维护。 如果您有一个平面数据集,则很可能要将其分解为其他存储选项之一。
关系数据库(MySQL,SQL Server)非常适合将数据存储在单独的表中,这些表可以使用唯一键进行连接。 这些方法的优点是它们可以减少数据集的大小,性能更好,并且可以使用完善的查询语言(SQL)进行访问。 该解决方案还需要进行大量规划,创建用于建立关系的唯一密钥以及性能调整。
面向文档的数据库(例如MongoDB )越来越流行,它允许您将数据存储在JSON对象中。 这也比平面文件更有效,因为数据的结构可以减少冗余。 以JavaScript固有的格式存储数据还有一个额外的优势,但是如果您试图合并多个数据集或汇总/创建聚合,则数据存储会变得越来越复杂。
非结构化数据库(例如Hadoop)适用于超大型数据集,不在本讨论范围之内。 如果您正在使用这种大小的数据集,则可能需要在将其引入应用程序之前使用ETL流程对数据进行规范化。
客户端存储数据的选项也很吸引人,但这并非没有缺点。 在某些用例中,文件存储和在客户端计算机上缓存数据具有某些优点,但需要您和用户之间的一定程度的信任。 如果这是一项受信任的服务,或者用户知道他们将使用大量数据,则可以合理地期望他们允许访问文件存储。 但是,默认情况下,除了最苛刻的用例之外,我不建议您将此作为期望。
创建访问层
有几种方法可以为数据创建访问层。 长期以来, 视图一直是关系数据库中执行此操作的标准方法。 视图允许您围绕数据编写查询,并将其显示为表格。 使用数据攻击技术(例如分组依据,排序依据,总和等),可以为可视化和分析创建更小,更有针对性的数据集。
CREATE VIEW population_vw AS
SELECT country, age, year,
sum(total) AS TOTAL
FROM census_data
WHERE year IN ('2010')
AND country IN ('United States')
GROUP BY country, age, year;
大多数关系数据库还允许创建实例化视图,这些视图需要ETL创建视图,但性能更好,因为它们只需要访问一个表即可。
混合方法也可能有效。 通常,这可以通过为存储在SQL Server中的较大数据集创建更具针对性的MongoDB层来实现。 将最关键的数据卸载到面向文档的数据库,以便快速访问和使用,同时将全部数据存储在后端SQL数据库中。 如果您使用的是Node,则可以使用Express来管理这些数据集的创建并将其存储在MongoDB服务器上。
OLAP还允许您创建可以聚合的数据集,但可以预先建立要用来表示数据的维度和度量。 OLAP使用多维表达式(MDX)来访问数据类型,但是在Web应用程序中并不是很好的支持。
网络依赖
在将数据发送给客户端之前先对其进行汇总一直被认为是最佳做法。 最有可能的是,您希望在将数据呈现给用户之前,尽可能减少服务器上的数据。 但是,这可能很麻烦,因为您经常会被诱惑将其简化为服务器上最聚合的形式。 如果用户想要更改数据的布局,则会导致网络混乱,因为您始终需要以适当的聚合级别从服务器提取数据集。
至关重要的是,您要找到一种介质,在该介质中,数据被聚合到一个从带宽角度来看很重要的大小,而且还提供了足够的详细信息以进行分析。 这可以通过收集需求并建立最终用户分析所需的关键指标和维度来实现。
访问数据的常用方法之一是通过RESTful API。 RESTful API使您可以从远程服务器请求数据并在应用程序中使用它。 通常,这将是JSON格式。 实际上,建议减少HTTP调用次数,因为每个请求都会有一定程度的延迟。 您应该尝试将数据减少到服务器上不太详细但未完全聚合的级别,并存储要进一步减少的客户端数据集。
为了使API请求更加明确,可以使用GraphQL ,它允许您针对API制定查询。 使用GraphQL这样的语言,您可以轻松提取特定的数据子集。 GraphQL迅速成为应用程序的标准,这些应用程序在多个分类法之间具有复杂的关系,例如Facebook。
功能,工具和技术
从ES5开始,JavaScript在数组原型中内置了很多工具。 其中包括filter()
,它允许您获取一个数组并仅返回与查询相关的那些元素, reduce()
聚合您的数据并返回一个易于使用的汇总数据集,以及map()
,它可以用于更改数据中的值的表示方式。 它们得到了很好的支持,不需要更改原始数组,也不需要任何其他库。
要了解有关这些内置JavaScript函数的更多信息,请查看我们的有关函数式JavaScript编程的高级课程
对于数据表示,我个人比较喜欢D3 ,它允许您操纵DOM(尤其是SVG元素)以独特的方式表示数据。 范围从简单的条形图,折线图和饼图到复杂的交互式数据可视化。 我在D3中创建了全功能仪表板的演示 。 在本文的其余部分中,我们将引用此仓库中的代码。
如果您只是想添加一些无需大量自定义代码的快速可视化效果,那么其他一些更易于使用但可定制性较低的工具(例如Chart.js )非常有用 。
通常,当我在屏幕上呈现可视化效果时,我要做的就是将事件绑定到表单字段,该表单字段将在与页面上的SVG元素关联的对象上调用我们的render函数:
document.getElementById("total").addEventListener('click', function() {
barGraph.render(d, "total")
});
我们将传递数据集d
以及将要呈现的指标total 。 这将使我们能够做两件事:
- 通过获取数据集,我们可以最初对数据进行缩减和过滤,以及将值映射到“友好”名称
- 这将使我们能够从数据集中的各种不同指标中选择一个指标
在render函数中,我们将处理添加轴,工具提示,渲染视觉效果和更新。 通常这将分三个步骤进行:
render: function(d, m) {
this._init(d, m);
this._enter(d);
this._update(d);
this._exit();
}
这些是D3应用程序中的四个主要步骤:
- init –初始化比例尺,轴和数据集
- 输入 –生成初始视图更新
- 刷新 –更改数据集时的视图
- 退出 –清理
其他API,例如Chart.js,将允许您使用配置来创建图表,而不是从头开始构建图表。 这可以通过调用其API并传入所需的配置来完成:
var chartInstance = new Chart(ctx, {
type: "bar",
data: data,
options: {
legend: {
display: true,
labels: {
fontColor: "rgb(255, 99, 132)"
}
}
}
});
此处的区别是,您仅限于API中定义的形式和功能,而在构建唯一的和自定义的可视化效果时没有太大的灵活性。
这是我使用最多的两个库(D3和Chart.js),但是还有许多可用的其他选项(免费和付费)可用于向用户公开数据。 选择产品时,我会建议一些技巧:
- 获取使用Canvas / SVG构建的内容。 仍然令人惊讶地有许多基于Flash的应用程序(甚至是SilverLight)。 这些不是在考虑HTML标准的情况下构建的,当您尝试集成应用程序时,您会后悔。
- 考虑一下您团队的技能。 像D3这样的东西对于熟练的JavaScript开发人员团队来说非常有用,但是自定义程度较低的东西(例如ChartJS)可能就足以满足您团队的技能要求。
- 编程到接口。 如果最终将数据与应用程序过于紧密地结合在一起,那么如果您必须更换工具,则将需要更多的工作。
通常,您会发现自己正在使用多个数据集。 重要的是,如果要在前端将它们组合在一起,则要异步加载它们,并等待所有它们完全加载后再加入它们。 D3具有用于处理多个数据集的内置方法:
d3.queue()
.defer(d3.json, "data/age.json")
.defer(d3.json, "data/generation.json")
.await(function(error, d, g) {
如果要在汇总中显示数据,则可以使用D3的嵌套和汇总功能来提供此功能。 这将允许您轻松选择要汇总的维度(键)和指标
var grp = d3.nest()
.key(function(d) {
return d.generation;
})
.rollup(function(v) {
return d3.sum(v, function(d) {
return d.total;
})
})
.entries(dg);
性能与特点
在将数据传递给用户时要考虑的最重要的事情? 使他们能够分析数据而又不会使数据混乱。 这意味着控制他们必须使用多少个不同的维度/度量。 从性能的角度来看,这将有所帮助,因为您不会通过网络传递大型数据集,也不会限制需要在客户端进行的数字运算数量。
注意:这并不意味着将数据集缩减为完全聚合的数据集。 您希望它具有灵活性。 提供一组可以选择的四个或五个关键指标。 在数据集中还要保留一些不同的维度,以允许使用JavaScript的数组函数( filter
, reduce
和map
)或类似D3的库对数据进行分组和聚合。 用户在分析数据时应考虑性能和功能。
拥有数据集后,重要的是要知道如何呈现数据。 这是一个精简的JSON数据集的示例:
[{
"females": 1994141,
"country": "United States",
"age": 0,
"males": 2085528,
"year": 2010,
"total": 4079669
}, {
"females": 1997991,
"country": "United States",
"age": 1,
"males": 2087350,
"year": 2010,
"total": 4085341
}, {
"females": 2000746,
"country": "United States",
"age": 2,
"males": 2088549,
"year": 2010,
"total": 4089295
}, {
// ...
您可以从该数据集中看到一些维度(年龄,年份,国家/地区)和多个指标(女性,男性和总数)。 这将为我们提供足够的信息以图形方式显示,同时仍使我们能够以几种不同的方式对数据进行切片。
举例来说,假设我们要将数据分为相应的年龄段。 我们可以使用JavaScript的数组函数将年龄组汇总到X代,婴儿潮一代等,而无需对服务器进行任何其他调用并直接在客户端计算机上将其重新呈现在SVG中。
从演示中可以看到,我们为数据提供了一些不同的可视选项,并提供了一些用于过滤数据和选择指标的按钮。 这是使用户能够分析其数据的关键。
设置函数以呈现数据并设置所需的指标:
document.getElementById("total").addEventListener('click', function() {
barGraph.render(d, "total")
});
使用filter()
将数据缩小到适当的水平
document.getElementById("over50").addEventListener('click', function() {
const td = d.filter(function(a) {
return a.age >= 50
});
barGraph.render(td, "total");
});
将这些功能分配给文档中的过滤器,您就可以过滤数据集,更改指标并以任意方式对数据进行切片。
摘要
归根结底,您必须使用一种数据访问方法,该方法可帮助您的团队及其特定技能。 精心设计的数据存储层,适当的数据访问层以及正确的数据呈现前端工具将为您的用户提供坚实的报告基础。
我希望本文能为您概述创建数据驱动的应用程序时的重要注意事项。 如果您想了解更多信息,请在评论中让我知道!
From: https://www.sitepoint.com/data-management-visualization-javascript/