【D3.js in Action 3 精译_038】4.2 D3 折线图的绘制方法及曲线插值处理

news2024/11/25 17:12:46

当前内容所在位置(可进入专栏查看其他译好的章节内容)

  • 第一部分 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.3 将数据绑定到 DOM 元素
        • 3.3.1 利用数据给 DOM 属性动态赋值
      • 3.4 让数据适应屏幕
        • 3.4.1 比例尺简介(上篇)
        • 3.4.2 线性比例尺(中篇)
          • 3.4.2.1 基于 Mocha 测试 D3 线性比例尺(DIY 实战)
        • 3.4.3 分段比例尺(下篇)
          • 3.4.3.1 使用 Observable 在线绘制 D3 条形图(DIY 实战)
      • 3.5 加注图表标签(上篇)
        • 3.5.1 人物专访:Krisztina Szűcs(下篇)
      • 3.6 本章小结
    • 第四章 直线、曲线与弧线的绘制 ✔️
      • 4.1 坐标轴的创建(上篇)
        • 4.1.1 D3 中的边距约定(中篇)
        • 4.1.2 坐标轴的生成(中篇)
          • 4.1.2.1 比例尺的声明(中篇)
          • 4.1.2.2 坐标轴的添加(下篇)
          • 4.1.2.3 轴标签的添加(下篇)
      • 4.2 D3 折线图的绘制 ✔️
        • 4.2.1 直线生成工具的使用 ✔️
        • 4.2.2 对数据点作曲线插值处理 ✔️
      • 4.3 D3 面积图的绘制

文章目录

    • 4.2 折线图的绘制 Drawing a line chart
      • 4.2.1 直线生成工具的使用 Using the line generator
      • 4.2.2 对数据点作曲线插值处理 Interpolating data points into a curve

《D3.js in Action》全新第三版封面

《D3.js in Action》全新第三版封面

译者按
上一节我们学习了 D3 时间坐标轴与线性轴的绘制方法,这一节就可以正式开始折线图的绘制了,根据最终的示例效果,该折线图包含折线部分和面积图部分,本篇只涉及纯折线部分;面积图的实现则放到下一节介绍。

4.2 折线图的绘制 Drawing a line chart

下面实现数据可视化最常见的一类图表:折线图。折线图由连接各数据点的线段、或对这些数据点作插值计算而得到的曲线组成。它们通常用于展示某个现象随时间的演变过程。在 D3 中,这些线条和曲线由 SVG 路径元素(path elements)构建,其形状由 SVG 路径元素的 d 属性(attribute)决定。通过第 1 章的学习,我们知道了 d 属性是由一系列命令组成的;这些命令决定了绘制的形状。此外还提到过,d 属性很容易变得很复杂。所幸 d3-shape 模块提供了生成直线和曲线的工具函数,专门负责 d 属性的计算,从而简化了折线图的创建。

本节将绘制一条反映 2021 年纽约市平均气温变化趋势的直线/曲线,具体效果参考线上项目(http://mng.bz/5orB)或前面章节中的图 4.1。在此之前,先来绘制每个数据点。尽管折线图未必非要画出数据点,但它们有助于理解 D3 折线生成工具的工作原理。

由于专栏文章是分章节发表,这里直接给出图 4.1 的效果:

图 4.1 本章实现项目:2021 年纽约市温度变化及全年降水天数占比情况可视化

【图 4.1 本章实现项目:2021 年纽约市温度变化及全年降水天数占比情况可视化】

在函数 drawLineChart() 中,通过 D3 的数据绑定为数据集 weekly_temperature.csv 中的每一行创建一个 circle 元素,然后添加到选择集 innerChart 中,半径设为 4px。然后用 xy 方向的比例尺分别计算每个圆心的横纵坐标。

回忆一下第 3 章介绍的数据绑定相关知识点,这里需要用到访问器函数(accessor function)来访问每个圆上的绑定数据。在以下代码片段中,d 即为每个 circle 元素绑定的数据项。由于 data 是一个 JavaScript 对象,这里可以通过句点表示法拿到对应的日期和平均气温。相关知识点详见第 3 章 3.3.1 小节。

注意,这里特地声明了一个名为 aubergine (译注:读作 /ˈəʊbəʒiːn/,紫红色)的颜色常量,用于指定圆的 fill 属性值。因为示例项目还会多次用到该颜色,因此单独声明为一个常量。您也可以根据自己的喜好启用任意颜色:

const aubergine = "#75485E";
innerChart
  .selectAll("circle") // 利用数据绑定模式为数据集中的每一行添加一个圆
  .data(data)          
  .join("circle")      
    .attr("r", 4)
    .attr("cx", d => xScale(d.date)) // 根据绑定数据使用比例尺来定位数据点
    .attr("cy", d => yScale(d.avg_temp_F)) 
    .attr("fill", aubergine);

保存项目并在浏览器中查看图形,就能看到这些 circle 元素呈穹顶状分布于 29°F80°F 之间,如图 4.13 所示:

图 4.13 平均气温随时间变化的数据点绘制效果图

【图 4.13 平均气温随时间变化的数据点绘制效果图】

此处也可以绘制散点图(scatterplots)

走到这一步必须要强调的一个惊喜是,您已经在不知不觉间学会了 D3 散点图(scatterplots)的绘制!散点图 是一种简单的图表,用于展示 x 轴与 y 轴的数据点集合,可以直观地揭示两个或多个变量间的相关关系。

只要知道了坐标轴的绘制方法,再结合绑定数据定位屏幕上的每个数据点,您就完全可以绘制出一个散点图效果——这正是 D3 的魅力所在——不必特地去学怎样绘制特定的图表类型,而是通过创建并组合一些基本要素来构建可视化效果。对于散点图而言,这些基本要素甚至可以简单到仅仅包含两个坐标轴和一组 circle 元素。第 7 章我们还将实现一个散点图,让圆的面积根据变量的值而同步变化。

图 4.13.1 D3 散点图示例效果

【图 4.13.1 D3 散点图示例效果】

4.2.1 直线生成工具的使用 Using the line generator

至此,每个数据点的位置就画好了,接下来介绍 D3 的直线生成工具(line generator)。直线生成工具 d3.line() 是一个函数,它以各数据点的横纵坐标为输入,并将穿过这些数据点的 SVG 路径元素或折线(polyline)的 d 属性值作为输出。通常需要在直线生成器上链式调用 x()y() 两个访问器函数,并分别传入水平和垂直位置的坐标值,如图 4.14 所示:

图 4.14 直线生成工具 d3.line() 函数与访问器函数 x() 和 y() 的组合式写法。后者需分别将各数据点的横纵坐标作为参数传入。

【图 4.14 直线生成工具 d3.line() 函数与访问器函数 x() 和 y() 的组合式写法。后者需分别将各数据点的横纵坐标作为参数传入。】

下面来给折线图创建一个直线生成工具函数。首先调用 d3.line() 方法,然后分别链式调用访问器函数 x()y()x() 需要传入各数据点的水平坐标,这里通过参数 d 来访问每个绑定数据项,类似遍历数组时用到的循环变量。数据点的水平坐标可以通过对应的日期和水平比例尺函数 xScale() 计算得出;同理,垂直坐标则可以通过当天的平均气温结合纵向比例尺 yScale() 得到。最后将生成的工具函数赋给常量 lineGenerator 备用:

const lineGenerator = d3.line()
  .x(d => xScale(d.date)) // 每个数据点的水平位置
  .y(d => yScale(d.avg_temp_F)); // 每个数据点的垂直位置

接着,调用该工具函数,并将数据集 data 作为参数传入,其结果作为 path 元素 d 属性的属性值。

SVG 路径元素默认按黑色渲染图形,如果只想看到一条折线,则需要令 fill 属性为 nonetransparent,并将 stroke 属性(attribute)指定为想要的描边色;本例中即为 aubergine 紫红色。绘制效果如图 4.15 所示:

innerChart
  .append("path")
    .attr("d", lineGenerator(data)) // 利用行生成工具将数据集作为参数传入
    .attr("fill", "none")
    .attr("stroke", aubergine);

图 4.15 利用 D3 直线生成工具创建的 SVG 路径元素穿过每个数据点,形成了一条折线

【图 4.15 利用 D3 直线生成工具创建的 SVG 路径元素穿过每个数据点,形成了一条折线】

4.2.2 对数据点作曲线插值处理 Interpolating data points into a curve

在这个示例折线图中,离散数据点分布在整个数据范围内,用普通的折线段来连接数据点就能实现既定目标;但偶尔也会在数据点之间对数据作插值处理 1。为此,D3 提供了多种插值函数(interpolation functions)来生成曲线。

曲线生成工具是以 d3.line() 的访问器函数的形式出现的。要将刚才的直线工具函数变为曲线工具函数,只需要再链式调用一个访问器函数 curve() 即可,参数为 D3 的某个内置插值函数。如以下代码片段所示,传入参数为 d3.curveCatmullRom 2,它可以生成一个 立方样条曲线(cubic spline) (根据各数据点并结合三阶多项式函数计算得到的平滑而灵活的图形)。其渲染效果如图 4.16 所示。

const curveGenerator = d3.line()
  .x(d => xScale(d.date))
  .y(d => yScale(d.avg_temp_F)
  .curve(d3.curveCatmullRom);

图 4.16 利用 Catmull-Rom 插值算法绘制的折线图效果

【图 4.16 利用 Catmull-Rom 插值算法绘制的折线图效果】

关于最佳插值算法 What’s the best interpolation?

插值处理会修改数据呈现方式,不同的插值函数会产生不同的可视化效果。数据的可视化方式多种多样,从编程角度理解,这些方式方法都是合理的;但关键是让可视化效果传递客观实际(actual phenomena)。

由于数据可视化涉及统计原理的视觉呈现,因此也面临着误用统计数据带来的风险(dangers of misusing statistics)。其中线性插值是数据误用的重灾区,因为它能将看似粗糙的直线段处理成平滑自然的曲线段。

如图 4.17 所示,同一组折线数据在不同的曲线插值处理下将呈现不同的视觉效果。选择适当的插值函数很大程度上取决于目标数据集。在本节演示的折线图中,d3.curveBasis 会拉直曲线段的同时减少其变化,这显然不适合我们的示例数据。如果不在图表上绘制出数据点作对比,就无从知晓曲线段与这些数据点的误差。因此,甄选和测试曲线插值函数就显得尤为重要了。

图 4.17 不同的曲线插值处理对数据都有不同程度地修改

【图 4.17 不同的曲线插值处理对数据都有不同程度地修改】

与此同时,函数 d3.curveMonotoneXd3.curveCatmullRom 创建的插值曲线则紧挨数据点,与原始折线图相似;此外,d3.curveStep 函数还可以在适当的情况下对数据作另类处理。图 4.17 只给出了部分插值情况对比,还有一些插值工具还可以设置一些影响最终曲线形状的参数,具体配置情况,详见 d3-shape 模块相关文档。

这样 D3 折线图的绘制就完成了!再复盘梳理一下:首先需要初始化一个直线生成工具函数,并设置其访问函数 x()y(),如图 4.18 所示。这两个函数分别用于计算每个数据点的水平与垂直坐标;接着可以链式调用 curve() 访问器函数并指定插值算法,将直线段改为曲线段;最后,在绘图区添加 SVG 路径元素 path,并通过调用直线生成工具函数、传入数据集 data 来设置路径元素的 d 属性。第 7 章还将利用工具提示(tooltip)组件提升折线图的可交互性。如果想立即学习,也可以直接跳到该章节(译注:待翻译)。

图 4.18 D3 折线图的实现步骤

【图 4.18 D3 折线图的实现步骤】


  1. 插值 是一个数学和统计学领域的专用术语,指的是在已知数据点之间估算出新的数据点,常用于图表或曲线的平滑处理。 ↩︎

  2. d3.curveCatmullRomCatmull-Rom 样条,也叫 卡特穆尔-罗姆插值,它在计算机图形学和数据可视化领域应用广泛,是一种能够有效生成平滑曲线的数学方法描述。所谓样条(Spline),则是一种由多段多项式函数组成的分段函数,用于平滑地连接一组给定的点(即控制点)。样条通过一组控制点来定义,它们通常是数据的离散采样值。 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2234219.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构(8.7_2)——败者树

多路平衡归并带来的问题 什么是败者树 败者树的构造 败者树的使用 败者树在多路平衡归并中的应用 败者树的实现思路 总结

Web Broker(Web服务应用程序)入门教程(1)

1、介绍 Web Broker 组件(位于工具面板的“Internet”选项卡中)可以帮助您创建与特定统一资源标识符(URI)相关联的事件处理程序。当处理完成后,您可以通过编程方式构建 HTML 或 XML 文档,并将它们传输给客…

Redis高级篇之缓存一致性详细教程

文章目录 0 前言1.缓存双写一致性的理解1.1 缓存按照操作来分 2. 数据库和缓存一致性的几种更新策略2.1 可以停机的情况2.2 我们讨论4种更新策略2.3 解决方案 总结 0 前言 缓存一致性问题在工作中绝对没办法回避的问题,比如:在实际开发过程中&#xff0c…

Vue2进阶之Vue3高级用法

Vue3高级用法 响应式Vue2:Object.definePropertyObject.definePropertythis.$set设置响应式 Vue3:Proxy composition APIVue2 option API和Vue3 compositionAPIreactive和shallowReactivereadonly效果toRefs效果 生命周期main.jsindex.htmlLifeCycle.vue…

Unity3D学习FPS游戏(10)子弹攻击敌人掉血(碰撞检测)

前言:前面最然创造出带有血条的敌人,但子弹打中敌人并没有效果。所以本篇将实现子弹攻击敌人,并让敌人掉血。 子弹攻击敌人掉血 整体思路目标补充知识-碰撞检测 准备工作刚体和碰撞器添加添加刚体后子弹代码优化补充知识-标签系统Tag添加 碰…

AMD显卡低负载看视频掉驱动(chrome edge浏览器) 高负载玩游戏却稳定 解决方法——关闭MPO

问题 折磨的开始是天下苦黄狗久矣,为了不再被讨乞丐的显存恶心,一怒之下购入了AMD显卡(20GB显存确实爽 头一天就跑了3dmark验机,完美通过,玩游戏也没毛病 但是呢这厮是一点不省心,玩游戏没问题&#xff0c…

服装品牌零售业态融合中的创新发展:以开源 AI 智能名片 S2B2C 商城小程序为视角

摘要:本文以服装品牌零售业态融合为背景,探讨信息流优化和资金流创新的重要作用,并结合开源 AI 智能名片 S2B2C 商城小程序,分析其如何进一步推动服装品牌在零售领域的发展,提高运营效率和用户体验,实现商业…

【数据库】elasticsearch

1、架构 es会为每个索引创建一定数量的主分片和副本分片。 分片(Shard): 将索引数据分割成多个部分,每个部分都是一个独立的索引。 主要目的是实现数据的分布式存储和并行处理,从而提高系统的扩展性和性能。 在创建索…

语言模型的评测

语言模型的评测 内在评测 在内在评测中,测试文本通常由与预训练中所用的文本独立同分布的文本构成,不依赖于具体任务。最为常用的内部评测指标是困惑度(Perplexity) 困惑度是衡量语言模型对测试文本预测能力的一个指标&#xf…

Golang | Leetcode Golang题解之第535题TinyURL的加密与解密

题目: 题解: import "math/rand"type Codec map[int]stringfunc Constructor() Codec {return Codec{} }func (c Codec) encode(longUrl string) string {for {key : rand.Int()if c[key] "" {c[key] longUrlreturn "http:/…

德国卡赫携丰硕成果七赴进博会

第七届中国国际进口博览会于11月5日在国家会展中心(上海)正式拉开帷幕。作为全球最大的清洁设备和清洁解决方案提供商,“全勤生”德国卡赫连续七年参展,并携集团旗下子品牌HAWK霍克一同亮相技术装备展区3号馆,更带来多…

IT架构管理

目录 总则 IT架构管理目的 明确组织与职责 IT架构管理旨在桥接技术实施与业务需求之间的鸿沟,通过深入理解业务战略和技术能力,推动技术创新以支持业务增长,实现技术投资的最大价值。 设定目标与范围 IT架构管理的首要目的是确立清晰的组织…

Rust项目结构

文章目录 一、module模块1.文件内的module 二、模块化项目结构1.关于module2.各个模块之间互相引用 三、推荐项目结构1.实例 参考 一、module模块 1.文件内的module 关键字:mod 引入模块中的方法 usemod名字:方法名usemod名字.*写全路径 二、模块化…

HiveSQL 中判断字段是否包含某个值的方法

HiveSQL 中判断字段是否包含某个值的方法 在 HiveSQL 中,有时我们需要判断一个字段是否包含某个特定的值。下面将介绍几种常用的方法来实现这个功能。 一、创建示例表并插入数据 首先,我们创建一个名为employee的表,并插入一些示例数据&am…

408——计算机网络(持续更新)

文章目录 一、计算机网络概述1.1 计算机网络的概念1.2 计算机网络体系结构1.3 总结 二、物理层2.1 物理层的基本概念2.2 物理层的基本通信技术2.3 总结 三、数据链路层3.1 数据链路层基础概论3.2 数据链路层的通信协议 一、计算机网络概述 1.1 计算机网络的概念 计算机网络的定…

正反shell反弹的区分

在shell反弹中我们会根据参照物的不同来区分正反shell反弹。 本次我们需要使用win和kali进行实验: 在shell反弹中我们需要在win上面安装netcat(瑞士军刀)用于可以执行监听指令。 下载指导链接https://blog.csdn.net/qq_40359932/article/d…

CSS的配色

目录 1 十六进制2 CSS中的十六进制2.1 十六进制颜色的基本结构2.2 十六进制颜色的范围2.3 简写形式2.4 透明度 3 CSS的命名颜色4 配色4.1 色轮4.2 互补色4.3 类似色4.4 配色工具 日常在开发小程序中,客户总是希望你的配色是美的,但是美如何定义&#xff…

Java 基于SpringBoot+Vue 的公交智能化系统,附源码、文档

博主介绍:✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取源码联系🍅 👇🏻 精彩专栏推荐订阅👇…

qt QFile详解

1、概述 QFile类是Qt框架中用于读取和写入文本和二进制文件资源的I/O工具类。它继承自QFileDevice类,后者又继承自QIODevice类。QFile类提供了一个接口,允许开发者以二进制模式或文本模式对文件进行读写操作。默认情况下,QFile假定文件内容为…

react jsx基本语法,脚手架,父子传参,refs等详解

1,简介 1.1 概念 react是一个渲染html界面的一个js库,类似于vue,但是更加灵活,写法也比较像原生js,之前我们写出一个完成的是分为html,js,css,现在我们使用react库我们把html和js结…