当前位置: 首页 > news >正文

【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作

当前内容所在位置

  • 第一部分 D3.js 基础知识
    • 第一章 D3.js 简介(已完结)
      • 1.1 何为 D3.js?
      • 1.2 D3 生态系统——入门须知
      • 1.3 数据可视化最佳实践(上)
      • 1.3 数据可视化最佳实践(下)
      • 1.4 本章小结
    • 第二章 DOM 的操作方法(已完结)
      • 2.1 第一个 D3 可视化图表
      • 2.2 环境准备
      • 2.3 用 D3 选中页面元素
      • 2.4 向选择集添加元素
      • 2.5 用 D3 设置与修改元素属性
      • 2.6 用 D3 设置与修改元素样式
      • 2.7 本章小结
    • 第三章 数据的处理 ✔️
      • 3.1 理解数据
      • 3.2 准备数据 ✔️
        • 3.2.1 将数据集加载到 D3 项目 ✔️
        • 3.2.2 格式化数据 ✔️
        • 3.2.3 测量数据集 ✔️
      • 3.3 将数据绑定到 DOM 元素(精译中 ⏳)
      • 3.4 让数据适应屏幕
      • 3.5 加注图表标签
      • 3.6 本章小结

文章目录

    • 3.2 数据准备 Preparing data
      • 3.2.1 将数据集加载到 D3 项目 Loading a dataset into a D3 project
      • 3.2.2 格式化数据 Formatting a dataset
      • 3.2.3 测量数据集 Measuring a dataset

3.2 数据准备 Preparing data

有了数据集,下一步就是用 D3 将其 加载 到项目中,如图 3.8 中的步骤 2 所示。然后就是确保数据按正确的格式进行处理,其间也可能需要对数据进行多方位的测量。本节介绍的 D3 方法都是为了完成上述准备工作,并为示例条形图的创建提供有效数据。

图 3.8 D3 数据工作流的第二步即利用 D3 的数据获取方法,将数据集加载到项目中

图 3.8 D3 数据工作流的第二步即利用 D3 的数据获取方法,将数据集加载到项目中

3.2.1 将数据集加载到 D3 项目 Loading a dataset into a D3 project

D3 提供了极为方便的工具函数来处理项目数据的加载。具体工具函数的选择,取决于当前数据集的特定格式。例如,CSV 格式的数据集使用 d3.csv() 进行加载,JSON 数据集则使用 d3.json()。这些函数的第一个参数均为该数据文件的路径。此外,D3 还专门提供了用于加载文本甚至 XML 格式数据的工具函数。它们都分属 d3-fetch 模块(详见 https://d3js.org/d3-fetch)。

注意

本章代码已放到 GitHub 仓库(详见 http://mng.bz/Y7Po)。各章节代码都存放在代码仓库相应的文件夹下。在 3.2 开头的文件夹中可以看到本小节示例代码,数字后跟章节主题,如 3.2-Preparing_data。各文件夹下都有一组子文件夹 startend。若需从最基本的代码开始练习,请使用 start 文件夹。要是遇到困难,可以在 end 文件夹找到对应的参考代码。分章节练习时,建议一次只打开一个 start 或一个 end 文件夹。如果用 Live Server 工具一次性打开所有章节的文件并启动本地服务器,某些路径可能无法正常工作,尤其是往项目中加载数据集时,需要特别注意。

下面再回到上一章介绍过的那个条形图练习,将我们从《2021 年数据可视化行业状态调查》中搜集的样本数据集(详见 www.datavisualizationsociety.org/survey)加载到示例中。该数据集为 CSV 格式,位于 /data 文件夹下。数据集的具体内容如代码清单 3.1 所示。第一行为列标题,technologycount 分别表示调查中涉及的数据可视化工具(即从 ArcGISP5)、以及选用该工具的从业者投票数。其中 D3.js 为 414 票,Python 为 530 票:

代码清单 3.1 数据从业人员最常用的工具统计情况(data.csv)

technology,count
ArcGIS,147
D3.js,414
Angular,20
Datawrapper,171
Excel,1078
Flourish,198
ggplot2,435
Gephi,71
Google Data Studio,176
Highcharts,58
Illustrator,426
Java,29
Leaflet,134
Mapbox,167
kepler.gl,24
Observable,157
Plotly,223
Power BI,460
PowerPoint,681
Python,530
QGIS,193
Qlik,61
R,561
React,145
Tableau,852
Vega,48
Vue,51
Web Components,79
WebGL,65
Pen & paper,522
Physical materials,69
Canvas,121
P5/Processing,55

鉴于目标数据集为 CSV 文件,因此选用 d3.csv() 进行数据加载,并将文件路径 "../data/data.csv" 作为第一参数。这里的双句点符号 .. 表示上一层目录,即文件夹 /js 所在的项目根目录。然后进入 /data 文件夹,最终定位到数据文件 data.csv

d3.csv("../data/data.csv");

这样就完成了数据工作流中的第 2 步。接下来需要对数据做格式化处理并完成相关测量工作。在此之前,还要知道数据的访问方法。注意,这里的数据加载是一个 异步过程(asynchronous process,所涉及的异步操作,是指那些数据结果不会立即返回的数据请求。我们可以通过访问 d3.csv() 的回调函数,或者 JavaScriptPromise 接口,确保数据在执行相关操作前已加载完毕。

3.2.2 格式化数据 Formatting a dataset

本节介绍 D3 处理数据格式的具体方法,对应工作流中的第三步,如图 3.9 所示:

图 3.9 数据工作流的第三步,从数据格式化开始,以便在构建可视化时使用

图 3.9 数据工作流的第三步,从数据格式化开始,以便在构建可视化时使用

d3.csv() 中的回调函数,又称为 行转换函数(row conversion function),能够逐行访问数据。在下面的代码中,d3.csv() 的第一个参数为数据路径,第二个参数即为回调函数。该函数将访问到的数据输出到控制台显示。复制本段代码到 main.js 并保存项目:

const svg = d3.select(".responsive-svg-container").append("svg").attr("viewBox", "0 0 1200 1600").style("border", "1px solid black");d3.csv("../data/data.csv", d => {console.log(d);
});

打开浏览器检查工具,转到控制台(即 Console)标签,将会看到如图 3.10 所示的输出结果。数据逐行记录,每一行都是一个包含 technologycountJavaScript 对象:

图 3.10 获取到数据后,由 d3.csv() 回调函数输出到控制台的部分数据显示情况

图 3.10 获取到数据后,由 d3.csv() 回调函数输出到控制台的部分数据显示情况

d3.csv("../data/data.csv", d => {return {technology: d.technology,count: +d.count};
});

这里的关键在于,回调函数中返回的这些键值对(key-value pairs),是数据集加载完毕后唯一可以访问的内容。该策略可以有效过滤原始数据中的无关字段列。但如果需要保留的列过多,逐一返回目标键值对可能稍显冗余。这时可能需要跳过回调函数中的处理逻辑,待 D3 返回完整数据集后再统一进行格式化。完整数据集的具体访问方法将在下一节进行介绍。

3.2.3 测量数据集 Measuring a dataset

D3 数据工作流的第三步还可以包含一个可选操作,即数据测量,如图 3.11 所示。尽管逐行读取数据很实用,但有时也需要访问整个数据集。这就要用到 JavaScript 的期约接口 Promise 了。Promise 是异步操作的结果,并以对象的形式存在。例如函数 d3.csv() 返回的对象。读取 Promise 结果的一个简单方法是调用其 then() 方法。

图 3.11 在第三步的第二小步,可以测量并探索数据

图 3.11 在第三步的第二小步,可以测量并探索数据

在以下代码段中,工具函数 d3.csv() 链式调用了 then() 方法。一旦数据加载完毕,Promise 即转为 兑现(fulfilled) 状态,完整数据集将在 then() 方法中的回调函数中备用。按如下代码将该数据集一次性输出到控制台,并保存项目:

d3.csv("../data/data.csv", d => {return {technology: d.technology,count: +d.count};
}).then(data => {console.log(data);
});

在控制台中,您会看到一个被转换为对象数组的完整数据集,其中的每个对象对应 CSV 原始数据集中的某一行。此时 D3 让该数据集变为可迭代对象,对于后续可视化开发非常有用。如图 3.12 所示,还可以确认计数值已正确转为数字形式。查看数组最后一项,还能看到经过 D3 处理后的原始 CSV 数据的列标题数组。尽管我们的条形图小练习暂不需要,但它偶尔也可以派上用场。

图 3.12 完整的数据集以对象数组的形式记录在控制台中

图 3.12 完整的数据集以对象数组的形式记录在控制台中

在数据工作流的第 3.a 步骤中,我们已经完成了数据格式化的工作,此时仍然可以利用 D3 来探索并测量获取到的数据。测量数据的特定维度有助于提前做好相关准备工作。

虽然从何处开始探索数据并没有严格的规范,但从数据集 Promise 的 then() 方法切入不失为一个好思路。首先要考察数据集包含了多少种技术。这可以通过数组的 length 属性直接查看。打印到控制台,将得到结果 33。也就是说,条形图将包含 33 个矩形元素:

d3.csv("../data/data.csv", d => {...
}).then(data => {console.log(data.length);   // => 33(数据集包含的总行数)
});

此外,我们还想知道哪种技术最受欢迎,以及有多少从业人员在定期使用它;最热门的有了,最冷门的情况又如何?这些指标都可以通过 d3.max()d3.min() 函数获得。如以下代码段所示,这些函数都接受两个参数:第一个参数是包含这些极值的可迭代对象(即数据集本身),由 Promise 提供;第二个参数是一个 访问器函数(accessor function),用于指定参与比较的健(本例中即为 count)。

若要在控制台中分别输出最大值和最小值,同样可利用 Promisethen() 方法,分别得到结果 107820

d3.max(data, d => d.count)      // => 1078
d3.min(data, d => d.count)      // => 20
d3.extent(data, d => d.count)   // => [20, 1078]

注意

还可以使用 d3.extent() 方法,它接受相同的参数并返回一个包含最小值和最大值的结果数组。

考察数据中的最大值与最小值有助于预判图表中条形区域的长度,并能预估最高值和最低值之间的差异对比是否易于在屏幕上渲染。

条形图中的数据常按降序排列,这样可读性更强,观众看了也能一目了然,明确哪些技术使用频率较高、哪些较低。JavaScript 的原生方法 sort() 可以轻松实现排序。它接受一个 比较函数(compare function) 作参数,如以下代码所示。该函数用于比较两个技术的 count 值,参数 a 和参数 b 分别表示参与比较的两个技术对象。若 b 中的 count 值大于 a 中的,则 b 应该排在 a 的前面,以此类推:

data.sort((a, b) => b.count - a.count);

排序逻辑可以放到 then() 方法内。如果打印到控制台,会看到 Excel 位于技术列表的首位,计数为 1078;其次是 Tableau,计数值 852Angular 则以 20 的最小计数值垫底,如图 3.13 所示。

此外,d3-array 模块(详见 https://d3js.org/d3-array)还包含大量用来测量及转换数据的实用方法,本书后续将选取一部分进行介绍。但 d3.max()d3.min()d3.extent() 函数应该这当中是最常用的。

图 3.13 输出到控制台并按降序排列的数据集

图 3.13 输出到控制台并按降序排列的数据集

完成了数据的加载、转换与测量工作,接下来通常需要将数据集传递给另一个函数进行处理。该函数负责可视化效果的构建。如以下代码段所示,可以看到此时 main.js 中的内容;注意观察在 then() 方法的末尾,数据是怎样传递给 createViz() 函数的。该函数的实现逻辑将在下一节进行介绍。

代码清单 3.2 数据的加载、转换与测量逻辑(main.js)

const svg = d3.select(".responsive-svg-container").append("svg")  // 添加一个 SVG 容器.attr("viewBox", "0 0 1200 1600")     .style("border", "1px solid black");  d3.csv("../data/data.csv", d => { // 加载数据集// 对数据进行格式化处理return {technology: d.technology,  count: +d.count            };
}).then(data => {// 对数据集进行测量console.log(data.length); // => 33console.log(d3.max(data, d => d.count)); // => 1078         console.log(d3.min(data, d => d.count)); // => 20          console.log(d3.extent(data, d => d.count)); // => [20, 1078]// 让数据集按降序排列data.sort((a, b) => b.count - a.count);// 将数据集传给另一个函数作进一步处理createViz(data);
});// 构建条形图的处理函数
const createViz = (data) => {};

在结束本节内容前,您可以参照图 3.14 中的内容,简要回顾一下前面学过的数据加载、行转换以及 Promise 等相关概念。总结归纳如下:

  1. 加载数据要用到 D3 的数据获取函数(fetch function),如 d3.csv()
  2. 数据的格式化是在行转换函数中进行的。
  3. 数据加载完毕后,可以通过链式调用 then() 方法来访问整个数据集。该方法也是探究数据及执行其他数据操作的理想场所。
  4. 将最终的数据传递给另一个函数,由该函数负责具体的可视化构建。

图 3.14 D3 中数据加载、转换及测量的实现方法与位置示意图

图 3.14 D3 中数据加载、转换及测量的实现方法与位置示意图

相关文章:

【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介(已完结) 1.1 何为 D3.js?1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践(上)1.3 数据可视化最佳实践(下)1.4 本章小结 第二章…...

电脑怎么禁用软件?5个方法速成,小白必入!

电脑禁用软件的方法多种多样,以下是五种简单易行的方法. 适合不同需求的用户,特别是电脑小白。 1. 使用任务管理器禁用启动项 操作步骤:按下“Ctrl Shift Esc”组合键,打开任务管理器。 切换到“启动”选项卡,找到…...

力扣之181.超过经理收入的员工

文章目录 1. 181.超过经理收入的员工1.1 题干1.2 准备数据1.3 题解1.4 结果截图 1. 181.超过经理收入的员工 1.1 题干 表:Employee -------------------- | Column Name | Type | -------------------- | id | int | | name | varchar | | salary | int | | mana…...

C++语法应用:从return机制看返回指针,返回引用

前言 编程是极其注重实践的工作,学习的同时要伴随代码 引入 此前对返回指针和引用有一些纠结,从return角度来观察发生了什么。 return机制 函数中return表示代码结束,如果return后面有其他代码将不被执行。 return发生了值转移,return后面的…...

Linux5-echo,>,tail

1.echo命令 echo是输出命令,类似printf 例如:echo "hello world",输出hello world echo pwd,输出pwd的位置。是键盘上~ 2.重定向符> >> >指把左边内容覆盖到右边 echo hello world>test.txt >…...

sqlgun靶场训练

1.看到php?id ,然后刚好有个框,直接测试sql注入 2.发现输入1 union select 1,2,3#的时候在2处有回显 3.查看表名 -1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schemadatabase()# 4.查看列名…...

简化登录流程,助力应用建立用户体系

随着智能手机和移动应用的普及,用户需要在不同的应用中注册和登录账号,传统的账号注册和登录流程需要用户输入用户名和密码,这不仅繁琐而且容易造成用户流失。 华为账号服务(Account Kit)提供简单、快速、安全的登录功能,让用户快…...

【研发日记】嵌入式处理器技能解锁(六)——ARM的Cortex-M4内核

文章目录 前言 背景介绍 指令集架构 ARM起源 ARM分类 Cortex-M4 内核框架 指令流水线 实践应用 总结 参考资料 前言 见《【研发日记】嵌入式处理器技能解锁(一)——多任务异步执行调度的三种方法》 见《【研发日记】嵌入式处理器技能解锁(二)——TI C2000 DSP的SCI(…...

深度学习经典模型之T5

T5(Text-to-Text Transfer Transformer) 是继BERT之后Google的又外力作,它是一个文本到文本迁移的基于Transformer的NLP模型,通过将 所有任务统一视为一个输入文本并输出到文本(Text-to-Text)中,即将任务嵌入在输入文本中,用文本的…...

10.第二阶段x86游戏实战2-反编译自己的程序加深堆栈的理解

免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 工具下载: 链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd6tw3 提…...

ARM总复习

1.计算机的组成 输入设备 输出设备 存储设备 运算器 控制器、总线 2.指令和指令集 2.1 机器指令 机器指令又叫机器码,在运算器内部存在各种运算电路,当处理器从内存中获取一条机器指令,就可以按照指令让运算器内部的指定的运算电路进行运…...

​​使用ENVI之大气校正(下)

再根据遥感影像的拍摄时间将Flight ate与Flight Time GMT (H:M:SS)填写,如要查询按如下方法 这里按照表中的内容修改 根据影像范围的经纬度与拍摄时间更改Atmospheric Model,更改完成后点击Multispectral Settings...在跳出的界面中选择GUI再点击Default…...

C++(学习)2024.9.18

目录 C基础介绍 C特点 面向对象的三大特征 面向对象与面向过程的区别 C拓展的非面向对象的功能 引用 引用的性质 引用的参数 指针和引用的区别 赋值 键盘输入 string字符串类 遍历方式 字符串与数字转换 函数 内联函数 函数重载overload 哑元函数 面向对象基…...

认知小文2《成功之路:习惯、学习与实践》

内容摘要: 在这个充满机遇的时代,成功不再是偶然,而是可以通过培养良好习惯、持续学习和实践来实现的目标。    一、肌肉记忆:技能的基石 成功往往需要像运动员一样,通过日复一日的练习来形成肌肉记忆。无论是健身…...

【数据仓库】数据仓库层次化设计

一、基本概念 **1. RDS(RAW DATA STORES,原始数据存储)** RDS作为原始数据存储层,用于存储来自各种源头的未经处理的数据。这些数据可能来自企业内部的业务系统、外部数据源或各种传感器等。RDS确保原始数据的完整性和可访问性&…...

【DAY20240918】03教你轻松配置 Git 远程仓库并高效推送代码!

文章目录 前言 git diff一、远程仓库?1、在 Gitee 上新建仓库:2、Git 全局设置:3、添加远程仓库:4、推送本地代码到远程仓库:5、输入用户名和密码:6、后续推送: 二、全情回顾三、参考 前言 git …...

从IPC摄像机读取视频帧解码并转化为YUV数据到转化为Bitmap

前言 本文主要介绍根据IPC的RTSP视频流地址,连接摄像机,并持续读取相机视频流,进一步进行播放实时画面,或者处理视频帧,将每一帧数据转化为安卓相机同格式数据,并保存为bitmap。 示例 val rtspClientListener = object: RtspClient.RtspClientListener {override fun …...

LeetCode 面试经典 150 题回顾

目录 一、数组 / 字符串 1.合并两个有序数组 (简单) 2.移除元素 (简单) 3.删除有序数组中的重复项 (简单) 4.删除有序数组中的重复项 II(中等) 5.多数元素(简单&am…...

【网络安全的神秘世界】渗透测试基础

🌝博客主页:泥菩萨 💖专栏:Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 渗透测试基础 基于功能去进行漏洞挖掘 1、编辑器漏洞 1.1 编辑器漏洞介绍 一般企业搭建网站可能采用了通用模板&#xff…...

【重学 MySQL】二十九、函数的理解

【重学 MySQL】二十九、函数的理解 什么是函数不同 DBMS 函数的差异函数名称和参数功能实现数据类型支持性能和优化兼容性和可移植性 MySQL 的内置函数及分类单行函数多行函数(聚合函数)使用注意事项 什么是函数 函数(Function)在…...

MySQL5.7主从复制搭建-gtid方式

环境准备 1、主机名和和IP地址如下 10.0.0.51 db01.ljbb.com 10.0.0.52 db02.ljbb.com 10.0.0.53 db03.ljbb.com2、配置文件 db01 [mysqld] usermysql basedir/app/mysql datadir/data/mysql/data socket/tmp/mysql.sock server_id51 port3306 secure-file-priv/tmp autoco…...

golang学习笔记22——golang微服务中数据竞争问题及解决方案

推荐学习文档 golang应用级os框架,欢迎stargolang应用级os框架使用案例,欢迎star案例:基于golang开发的一款超有个性的旅游计划app经历golang实战大纲golang优秀开发常用开源库汇总想学习更多golang知识,这里有免费的golang学习笔…...

yolo训练出现Could not load library libcudnn_cnn_train.so.8问题及解决方法

问题场景: 训练yolov5或者yolov8时候会报错: Could not load library libcudnn_cnn_train.so.8. Error: /usr/local/cuda-12.1/lib64/libcudnn_cnn_train.so.8: uined symbol: _ZN5cudnn3cnn34layerNormFwd_execute_internal_implERKNS_7backend11Vari…...

携手科大讯飞丨云衔科技为企业提供全栈AI技术解决方案

作为智能时代的核心驱动力,人工智能不仅重塑了传统行业的面貌,更开辟了全新的经济增长点。科大讯飞以其深厚的技术底蕴和创新能力,持续引领着人工智能领域的发展潮流。云衔科技作为科大讯飞开放平台的AI技术产品线合作伙伴代理商,…...

57页PPT | 智慧文旅整体建设解决方案

主要介绍了智慧文旅的建设背景、需求分析、解决方案、应用系统功能需求、客户价值、企业价值、建设理念、建设思路、总体架构、安全管理体系、融媒体综合服务平台、大数据分析平台、智慧文旅云平台、智慧管理、智慧营销、智慧服务等方面的内容。 背景及需求分析 方案架构及理念…...

线性代数之QR分解和SVD分解

文章目录 1.QR分解Schmidt正交化Householder变换QR分解的应用 2. 求矩阵特征值、特征向量的基本方法3.SVD分解SVD分解的应用 参考文献 1.QR分解 矩阵的正交分解又称为QR分解,是将矩阵分解为一个正交矩阵Q和一个上三角矩阵R的乘积的形式。 任意实数方阵A&#xff0c…...

在虚拟机安装mysql数据库

一、安装步骤(下载包-传输软件包-安装包-启用仓库-使用yum安装服务器) 1、要在mysql官网下载yum仓库包 2、下载好rpm包后,将其通过xftp传输到root目录下 3、使用sudo yum install yum的仓库名(sudo yum install mysql-community-…...

详解QT插件机制

Qt插件机制允许将功能模块化为独立的插件,从而在运行时动态加载和卸载这些模块。这种机制对于扩展应用程序、插件架构和动态功能添加非常有用 插件机制 插件的基本概念 插件: 在Qt中,插件是实现特定接口的动态库(DLL或so文件),这些接口由Qt插件框架定义。插件可以被应用程序…...

【Hot100】LeetCode—32. 最长有效括号

目录 1- 思路题目识别动态规划 2- 实现⭐32. 最长有效括号——题解思路 3- ACM 实现 原题链接:32. 最长有效括号 1- 思路 题目识别 识别1 :给定一个字符串 s ,求解 s 中的最长有效括号 动态规划 动态规划五部曲 递推公式难如果遇到了 s.…...

力扣198-打家劫舍

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的…...