数据生成、分箱与分组 — 从造数据到造结构
数据生成、分箱与分组 — 从造数据到造结构
这一章讲什么: 数据的「无中生有」与「由平变立」。 上半讲生成:d3-range 造等差序列、d3-random 造随机分布、d3-interpolate 造中间值、 d3-time 造时间区间;下半讲两件压轴的事——分箱(把一列数切成桶,画直方图)和 分组(把平表折叠成树,喂给层级图)。原书说这两件「covered in depth」1,是本章真正的肉。
1. 顶层全景:本章工具的三个去向
造数据 造中间值 造结构
├─ d3.range / d3.ticks ├─ d3.interpolate(插值) ├─ d3.bin → 直方图的桶
├─ d3-random*(17 种分布) └─ d3.blur / blur2(平滑) └─ d3.group/rollup 家族 → 层级数据
└─ d3-time*(时间区间) (d3-time 也在这里)
│ │ │
└─────────── 全部服务于「绑数据之前」这一步 ──────────┘
图说:生成的数据用于测试和演示;插值/平滑用于修曲线;分箱和分组的产物直接决定图的结构。2. 生成序列:range 与 ticks
d3.range 就是 Python 的 range:造等差数列,不含终点2:
d3.range(10) // [0,1,2,3,4,5,6,7,8,9]
d3.range(-3, 3) // [-3,-2,-1,0,1,2]
d3.range(0,10,2) // [0,2,4,6,8]
d3.range(1, 2, .2) // [1, 1.2, 1.4, 1.6, 1.8]
图说:三个参数是 (起点, 终点, 步长);只给一个参数时起点默认 0、步长默认 1。d3.ticks(start, stop, count) 造圆整的刻度值:不求精确 count 个,
而是挑 1、2、5×10 的幂这样「好看」的数——它是 D3 坐标轴生成刻度的内部工具3:
d3.ticks(-25, 75, 5) // [-20,0,20,40,60] —— 请求 5 个,给了 5 个
d3.ticks(-25, 75, 7) // [-20,0,20,40,60] —— 请求 7 个,还是这 5 个!参数只是建议想要包含端点,先用 d3.nice(25,75,4) 得到放宽的区间 [-40,80],
再 d3.ticks(-40,80,7) 得 [-40,-20,0,20,40,60,80];
d3.tickStep(-25,75,4) 单独返回算出来的步长 204。
3. 随机分布:d3-random
原生 Math.random() 给 0–1 之间的均匀分布,且每次运行结果不同。
d3-random 提供 17 种分布的随机数生成器(v7),常用四个5:
| 函数 | 分布 |
|---|---|
d3.randomUniform(min, max) | 均匀分布(整数用 d3.randomInt) |
d3.randomNormal(μ, σ) | 正态(高斯)分布:均值 μ,标准差 σ |
d3.randomLogNormal(μ, σ) | 对数正态 |
d3.randomExponential(λ) | 指数分布 |
函数生成函数:先造生成器,再反复调用取数——
const normal = d3.randomNormal(100, 15); // 均值 100、标准差 15 的生成器
const values = d3.range(10000).map(() => normal()); // 一万个样本
// 画成直方图就是一座钟形小山(本节后面就画它)
图说:d3.range(10000) 先造一万个占位下标,map 里逐个换成随机数——
「造序列」和「造随机」在这行代码里合流。播种(seed):默认随机源是 Math.random(),不可复现。换上线性同余生成器
(LCG,linear congruential generator)并给它种子,同样的种子出同样的序列——
调试、测试、做演示数据时关键6:
const seededRand = d3.randomInt.source(d3.randomLcg(123));
seededRand(0,100) // 每次运行都得 [28, 43, 3, 22, 35]——这些数照原书
const rand = d3.randomInt; // 默认源
rand(0,100) // 每次不同洗牌:d3.shuffle(数组) 原地洗牌(Fisher-Yates 算法);
d3.shuffler(随机源) 造一个指定随机源的洗牌函数,带种子可复现:
d3.shuffler(d3.randomLcg(42))([1..9]) 永远得 [9,4,7,8,6,2,5,1,3]7。
4. 生成中间值:插值与模糊
4.1 d3.interpolate:一切过渡的引擎
**插值(interpolation)**是在两个值之间造中间值的过程。它是 D3 过渡动画的引擎, 平时藏在 transition 背后,本章把它单独拿出来8:
const interpolate1 = d3.interpolate(23, 123); // 造一个插值函数
interpolate1(0) // 23 —— t=0 是起点
interpolate1(0.25) // 49.5
interpolate1(0.5) // 74
interpolate1(1) // 123 —— t=1 是终点
图说:插值函数吃一个 0~1 的 t,吐出从 a 到 b 按比例推进的值。
transition 动画每一帧就是在算一个新的 t。d3.interpolate(a, b) 的聪明之处:看 b 的类型自动选插值器——
d3.interpolate("Part 0 of 100", "Part 100 of 100")
interpolate2(0.25) // 'Part 25 of 100' —— 字符串里的数被找到并插值
d3.interpolate(new Date(2023,10,14), new Date(2024,4,8))
interpolate3(0.5) // '2024-02-10' —— 日期按毫秒数插
d3.interpolate([3,10,100],[30,100,0])
interpolate4(0.5) // [16.5, 55, 50] —— 数组逐项插
d3.interpolate("red", "blue")
interpolate4(0.25) // 'rgb(191, 0, 64)' —— 颜色走 RGB 空间
d3.interpolate({a:-30, b:'red'}, {a:50, b:'blue'})
interpolate5(0.5) // {a:10, b:'rgb(128,0,128)'} —— 对象逐属性插配套工具:interpolateRound(整数版)、interpolateDiscrete(把 0–1 切段、各配一个数组值)、
d3.quantize(插值器, n)(从插值器里均匀采 n 个样)、d3.piecewise(数组里逐对插)9。
颜色的插值在第 10 章展开,更多插值器在第 14 章交互里出现10。
4.2 d3.blur:移动平均平滑
d3.blur(数组, 半径) 把每个值按半径摊给邻居——数组原地修改,
相邻点的距离被拉近,曲线变平滑11:
const data = [0,100,0,-100,0,100];
d3.blur(data, 0.5) // [31.3, 23.5, 1.6, -10.9, 10.9, 43.8]
图说:峰值 100 被摊薄到邻点(31.3、23.5…),谷值 -100 同样(变成 -10.9)。
半径越大越糊;反复调用效果累积。以上数值照原书。二维版本 d3.blur2({data, width, height}, rx, ry) 直接糊矩阵(热图、像素网格),
d3.blurImage(imageData, rx, ry) 糊画布上的真图片(ImageData 对象)12。
5. 时间区间:d3-time
JavaScript 的日期处理历来是坑(解析不一致、getYear() 这类老接口、没有时区和区间概念;
Temporal API 是未来的解,但书出版时还没普及)。d3-time 给的是**区间(interval)**这套抽象13:
预置区间从毫秒到年:d3.timeDay、d3.timeWeek(= timeSunday)、d3.timeMonth、d3.timeYear 等;
UTC 版本一套 d3.utcDay…。每个区间带一组方法,记四个最常用的:
| 方法 | 干什么 | 例子 |
|---|---|---|
offset(日期, 步数) | 加减区间步数 | timeYear.offset(now, 1) 一年后;timeMonth.offset(now, -1) 一个月前 |
floor/ceil/round(日期) | 取所在区间的下边界/上边界/最近边界 | 见下 |
range(起点, 终点) | 区间内所有边界组成的日期数组 | 一个月的每一天 |
count(a, b) | 两个日期间有多少个区间步 | 今年过了多少天 |
floor/ceil/round 对照(以某天上午 6 点和下午 6 点为例,本地时区)14:
d3.timeDay.floor(pm) // 当天 00:00 —— 所在日的起点
d3.timeDay.ceil(am) // 次日 00:00 —— 下一个日边界
d3.timeDay.round(am) // 当天 00:00 —— 6:00 离当天近
d3.timeDay.round(pm) // 次日 00:00 —— 18:00 离次日近
d3.timeDay(日期) // = floor(日期) 的别名count 的巧思:一周有 7 个以不同星期开始的预置区间,配合 count 算「距上周三几天」这类问题15:
d3.timeDay.count(d3.timeWeek(now), now) // 本周开始过了几天
d3.timeDay.count(d3.timeWednesday(now), now) // 距上周三过了几天
d3.timeHour.count(d3.timeYear(now), now) // 今年过了几小时range 生成日期数组,every(n) 抽稀、filter(测试) 定制——
「每 8 小时一次」「未来三天每天 9–17 点的工作时段」:
d3.timeDay.range(d3.timeMonth.offset(now, -1), now) // 过去 30 天,每天一个 Date
d3.timeHour.every(8).range(d3.timeDay.offset(now,-5), now) // 每 8 小时,15 个
d3.timeHour.filter(d => d.getHours() < 17 && d.getHours() > 9)
.range(now, d3.timeDay.offset(now,3)) // 未来 3 天的 9–17 点原书提醒:以上全按本地时间算;UTC 版本结果可能不同,且区间计算考虑每月天数和闰年、 不考虑夏令时16。
6. 分箱与直方图:d3.bin
6.1 什么是分箱
分箱(binning)把一列数(通常很大、或连续数据的离散采样)装进若干个桶: 每个桶是一段连续的、互不重叠的区间。用处两条:压缩(用区间代表原数据)、 看分布(统计每个区间里有多少个点)17。
桶数是个权衡,原书用同一份小数据给了三种切法:5 桶能看到中段稀疏、3 桶只剩「大部分挤在低处」、 11 桶则什么规律都看不出来。有算法能算「最优桶数」(Sturges、Scott、Freedman-Diaconis), 但原书的建议是:手动多试几个桶数,常常比算法更快发现有意思的东西18。
6.2 主线例子:直方图
本节把全章工具串成一个完整成品:一万个正态随机数的直方图。 输入、参数、每步产物全给具体值19:
① 造数据 data.values = d3.range(10000).map(d3.randomNormal(100, 15))
—— 均值 100、标准差 15 的一万个数
② 分箱 data.bins = d3.bin().thresholds(100)(data.values)
—— 约 100 个桶(实际可能更多);每个桶是一个数组,
附带 x0(下闭界)、x1(上开界)两个属性,桶长 = 桶里元素个数
③ 比例尺 scaleX = d3.scaleBand().range([25, 775])
.domain(data.bins.map(d => d.x0)) ← 桶的区间左界当类别
scaleY = d3.scaleLinear()
.range([600-25, 25]) ← y 轴翻转:大值在上
.domain([0, d3.max(data.bins, d => d.length)])
color = d3.scaleLinear()
.range(["darkgreen", "brown"]).domain(scaleY.domain()) ← 柱越高越红
④ 画柱 svg.selectAll("rect.bins").data(data.bins)
.join("rect")
.attr("x", d => scaleX(d.x0))
.attr("y", d => scaleY(d.length))
.attr("width", scaleX.bandwidth())
.attr("height", d => scaleY(0) - scaleY(d.length))
.style("fill", d => color(d.length));
图说:每个桶一根柱:横位置 = 桶的区间(x0),柱高 = 桶里数的个数(length),颜色随高度渐变。
正态分布的中间桶最高,向两边递减——钟形就是这么画出来的。分箱生成器的配置项:value(访问器)(对象数组取数值字段,如 d => d.diameterKm)、
domain([min,max])(只看某个区间)、thresholds(n或数组)(桶数建议或显式阈值数组)。
不传 thresholds 时用 Sturges 公式自动算;也可以把上一节的分位数当阈值——
四分位数切出来的桶宽度不等但样本数相近20:
const bin5 = d3.bin().thresholds([0, d3.quantile(data, .25),
d3.quantile(data, .5),
d3.quantile(data, .75)]); // [0, 3, 7, 15]7. 分组与嵌套:d3.group 家族
7.1 先解决输入形状:宽表转 tidy
分组工具的输入最好是 tidy 数据。原书的实战数据是圣保罗 1984–2017 年逐月降雨量: 宽表 35 行 × 13 列(Year + 12 个月份列),转成 tidy 是 408 行 × 3 列(Year, Month, Rain)21:
function makeTidyRow(row, _, headers) {
return headers.slice(1) // 跳过 Year 列,12 个月份
.map(h => ({ Year: +row.Year, Month: h, Rain: +row[h] }));
}
const tidyRows = await d3.csv(file, makeTidyRow);
const rainfall = tidyRows.flat(); // 每行返回 12 个对象,摊平成 408 行
// {Year: 1984, Month: 'Jan', Rain: 259.3}
// {Year: 1984, Month: 'Feb', Rain: 32.5} …
图说:行函数一行变十二行——宽表的「月份在列名里」被拍成了「月份在单元格里」。7.2 group / groups / index / rollup:同一个分组的四种返回形状
d3.group(数据, ...键函数) 按一个或多个键把平表折叠成嵌套结构。
键可以是多个——一级键先进、二级键后进,层层嵌套。四种形态的区别只在「返回什么容器」22:
| 函数 | 返回 | 取值方式 |
|---|---|---|
d3.group | 嵌套 Map | .get(键) 链式取 |
d3.groups | 嵌套数组的数组 | 按下标/遍历,适合直接绑数据 |
d3.index | 嵌套 Map(键必须唯一,否则抛错) | .get(键) 直接得对象,不用解数组 |
d3.rollup | 嵌套 Map,但叶子经过归并函数压缩 | 同上,叶子是算出来的值 |
主线例子走完(rainfall,408 行):23
① 按年分组(单键)
yearMap = d3.group(rainfall, k => k.Year)
// Map:1984 → [12 个月的对象],…,2017 → [12 个]
yearMap.get(2012) // 2012 年 12 个月的数组
yearMap.get(2012)[8] // {Year: 2012, Month: 'Sep', Rain: 19.2} ← 第 8 号是 9 月
② 按年+月两级分组(双键)
yearMonMap = d3.group(rainfall, k => k.Year, k => k.Month)
yearMonMap.get(2012).get('Sep') // [ {…} ] 数组(键可能多对一)
idxMap = d3.index(rainfall, k => k.Year, k => k.Month)
idxMap.get(2012).get('Sep') // {…} 直接是对象(键唯一才敢用)
③ 数组形态
yearArr = d3.groups(rainfall, k => k.Year)
// [[1984, [12 objects]], [1985, [12 objects]], …] ← 绑 D3 数据最顺手
yearMonArr = d3.groups(rainfall, k => k.Year, k => k.Month)
yearMonArr[28][1][8][1][0] // 2012 年 9 月——要钻五层:选哪个形态,看你取值深不深
④ 归并(rollup):分组时顺手算
valueMap = d3.rollup(rainfall, v => v.map(d => d.Rain)[0],
k => k.Year, k => k.Month)
valueMap.get(2012).get('Sep') // 19.2 —— 叶子直接是雨量,不再是对象数组
⑤ 摊平形态
d3.flatRollup(rainfall, v => v.map(d => d.Rain)[0],
k => k.Year, k => k.Month)
// [[1984,'Jan',259.3], [1984,'Feb',32.5], …] —— 一行一个三元组,永不深于两层
图说:同一份数据、同两把钥匙,五种形态。选型的判据原书给了一条:
「按特定键取值选 Map,绑嵌套结构选数组」。还有 d3.groupSort(数据, 排序, 键函数):生成排好序的唯一键列表,
原书的例子是 'Apr/1984', 'Aug/1984', …, 'Sep/2017'——给绑了数据的 SVG 元素派 id 时好用24。
8. 在线教程:降雨量热力表
章末教程把分组用到实战:圣保罗降雨 tidy 数据 → 按 Year × Month 分组 → 绑进一张 HTML 表格 → 单元格颜色用双色渐变(色阶由第 10 章的比例尺和插值器供)。 图形本身比前面的教程简单,难点全在数据折叠25。 练习的加分项:做成响应式、把 HTML 表格重构成 SVG 版26。
9. 作者的判断与证据
| 判断 | 性质 | 依据 |
|---|---|---|
| 「桶数多试比信算法强」 | 经验之谈 | 同一数据 3/5/11 桶的对比图18 |
| 「分组选 Map 还是数组,看取值还是绑定」 | 选型判据 | 配了「钻五层取值」的反面教材23 |
| 「tidy 最经洗,但第 12 章有例外」 | 有反例的法则 | 堆叠图要好宽表,第 12 章兑现21 |
10. 边界与局限
- 17 种随机分布只有 4 种有文字,其余一张直方图合集带过5;分布的数学定义不在书里。
d3.blur的「半径」语义原书没给公式,示例值(0.5、0.2)靠试11。- 时间区间不考虑夏令时;时区只有 UTC/本地两套16。
- 分组家族的内存开销(大平表折叠成深嵌套 Map)没有讨论。
判断(我们的,不是书里的): d3.group/rollup 这一组函数是 D3 里最像 SQL(数据库查询语言)的东西:
group是 GROUP BY、rollup 是 GROUP BY + 聚合、index 是「唯一键约束的分组」。 差别在于输出形态四种可选(Map/数组/摊平/归并),而 SQL 只给你一张表—— 这个「输出形态自由」恰是可视化需要的:绑 DOM 要数组,随机访问要 Map。 如果错,会错在: SQL 类比会让读者以为这些函数能做连接(join)——它们不能, 多表合并要先自己 merge/zip,分组只管单表折叠。
11. 可带走的
本章主线例子两行收束: 直方图——d3.range(10000).map(d3.randomNormal(100,15)) →
d3.bin().thresholds(100) 分桶 → band/linear 比例尺 + join 画柱;
分组——408 行 tidy 降雨数据 → d3.group(rainfall, d => d.Year, d => d.Month) 两级折叠 → 取值或绑表。
d3.range造等差序列(不含终点),d3.ticks造圆整刻度(参数只是建议);d3.randomNormal(μ,σ)等 17 种分布,.source(d3.randomLcg(seed))播种可复现;d3.shuffle原地洗牌,d3.shuffler(源)带种子;d3.interpolate(a,b)看 b 的类型自动选插值器:数字、字符串里的数、日期、数组、颜色、对象;d3.blur(数组, 半径)原地平滑,blur2 糊矩阵,blurImage 糊图片;- d3-time 区间:
offset加减、floor/ceil/round取边界、range造日期数组、count数步数; d3.bin()分箱:每桶是数组 +x0/x1区间属性,length是计数;value/domain/thresholds可调;- 直方图 = 分箱 + band(x0 当类别)+ linear(桶长当高度)+ join;
d3.group/groups/index/rollup是同一分组四种容器形态;flatGroup/flatRollup永不深于两层;- 选型:按键取值用 Map / index,绑嵌套 DOM 用数组形态;rollup 在分组时顺手聚合;
- 宽表转 tidy:行函数一行返回多行,
flat()摊平。
12. 原文地图
| 主题 | 原书章 | 原文位置 |
|---|---|---|
| 本章定位与「深度覆盖」声明 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:826(搜「Tools for data generation」) · text/14-ch07-chapter-7-working-with-data.txt:1738(搜「covered in depth」) |
| range/ticks/nice | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:837(搜「d3.range(stop)」) · text/14-ch07-chapter-7-working-with-data.txt:854(搜「[0,1,2,3,4,5,6,7,8,9]」) · text/14-ch07-chapter-7-working-with-data.txt:862(搜「[-20,0,20,40,60]」) · text/14-ch07-chapter-7-working-with-data.txt:869(搜「tickStep」) |
| 随机分布与正态例子 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:888(搜「17 functions」) · text/14-ch07-chapter-7-working-with-data.txt:897(搜「randomNormal(μ,σ)」) · text/14-ch07-chapter-7-working-with-data.txt:922(搜「randomNormal(100,15)」) · text/14-ch07-chapter-7-working-with-data.txt:931(搜「17 generators」) |
| 种子与洗牌 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:944(搜「randomLcg(seed)」) · text/14-ch07-chapter-7-working-with-data.txt:962(搜「28, 43, 3, 22, 35」) · text/14-ch07-chapter-7-working-with-data.txt:972(搜「Fisher-Yates」) · text/14-ch07-chapter-7-working-with-data.txt:987(搜「9,4,7,8,6,2,5,1,3」) |
| 插值器家族 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1001(搜「d3.interpolate(a,b)」) · text/14-ch07-chapter-7-working-with-data.txt:1026(搜「d3.interpolate(23, 123)」) · text/14-ch07-chapter-7-working-with-data.txt:1038(搜「Part 0 of 100」) · text/14-ch07-chapter-7-working-with-data.txt:1060(搜「{a:-30, b:'red'}」) |
| blur 三件套 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1074(搜「d3.blur(array,radius)」) · text/14-ch07-chapter-7-working-with-data.txt:1089(搜「[0,100,0,-100,0,100]」) · text/14-ch07-chapter-7-working-with-data.txt:1093(搜「31.3, 23.5」) · text/14-ch07-chapter-7-working-with-data.txt:1105(搜「blur2({data: imageData」) |
| d3-time 区间与方法 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1135(搜「timeInterval(floor,offset)」) · text/14-ch07-chapter-7-working-with-data.txt:1157(搜「count(start,end)」) · text/14-ch07-chapter-7-working-with-data.txt:1190(搜「a year from now」) · text/14-ch07-chapter-7-working-with-data.txt:1201(搜「Oct 19, 00:00」) · text/14-ch07-chapter-7-working-with-data.txt:1232(搜「Array(30 x Date)」) · text/14-ch07-chapter-7-working-with-data.txt:1237(搜「every(8)」) |
| 分箱概念与桶数权衡 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1268(搜「What are bins?」) · text/14-ch07-chapter-7-working-with-data.txt:1283(搜「none of these patterns is apparent」) |
| d3.bin 与生成的桶 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1293(搜「bingen = d3.bin()」) · text/14-ch07-chapter-7-working-with-data.txt:1322(搜「15, 9, 2, 13, 20」) · text/14-ch07-chapter-7-working-with-data.txt:1341(搜「bins[1]」) · text/14-ch07-chapter-7-working-with-data.txt:1363(搜「thresholds(3)」) · text/14-ch07-chapter-7-working-with-data.txt:1376(搜「bin5 = d3.bin()」) |
| 直方图完整代码 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1394(搜「randomNormal(100, 15)」) · text/14-ch07-chapter-7-working-with-data.txt:1399(搜「thresholds(100)」) · text/14-ch07-chapter-7-working-with-data.txt:1410(搜「scaleBand()」) · text/14-ch07-chapter-7-working-with-data.txt:1420(搜「darkgreen」) · text/14-ch07-chapter-7-working-with-data.txt:1424(搜「selectAll("rect.bins")」) |
| 宽表转 tidy | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1483(搜「Year,Jan,Feb,Mar」) · text/14-ch07-chapter-7-working-with-data.txt:1498(搜「makeTidyRow」) · text/14-ch07-chapter-7-working-with-data.txt:1509(搜「408 rows」) |
| group 家族函数表 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1529(搜「d3.group(iterable,…keys)」) · text/14-ch07-chapter-7-working-with-data.txt:1537(搜「throws an exception」) · text/14-ch07-chapter-7-working-with-data.txt:1542(搜「d3.rollup(iterable,reduce」) |
| 分组五种形态实跑 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1575(搜「yearMap = d3.group」) · text/14-ch07-chapter-7-working-with-data.txt:1596(搜「yearMonMap = d3.group」) · text/14-ch07-chapter-7-working-with-data.txt:1608(搜「idxMap = d3.index」) · text/14-ch07-chapter-7-working-with-data.txt:1614(搜「yearArr = d3.groups」) · text/14-ch07-chapter-7-working-with-data.txt:1647(搜「yearMonArr[28][1][8][1][0]」) · text/14-ch07-chapter-7-working-with-data.txt:1657(搜「valueMap = d3.rollup」) · text/14-ch07-chapter-7-working-with-data.txt:1689(搜「d3.flatRollup」) |
| groupSort 与热力图教程 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1709(搜「groupSort」) · text/14-ch07-chapter-7-working-with-data.txt:1715(搜「heatmap table」) |
| 章小结 | Working with Data | text/14-ch07-chapter-7-working-with-data.txt:1732(搜「Summary」) |
Footnotes
-
出处:「Working with Data」第 1737–1739 段(
text/14-ch07-chapter-7-working-with-data.txt:1738,搜「covered in depth」)。原文:「important features such as grouping and bins were covered in depth with practical applications.」 ↩ -
出处:「Working with Data」第 835–857 段(
text/14-ch07-chapter-7-working-with-data.txt:837,搜「d3.range(stop)」;:854,搜「[0,1,2,3,4,5,6,7,8,9]」)。d3.range(0,10,2) 原书注释为 [0,2,4,6,10],按定义应为 [0,2,4,6,8],此处以定义为准并保留原书注释存疑。 ↩ -
出处:「Working with Data」第 842–866 段(
text/14-ch07-chapter-7-working-with-data.txt:842,搜「d3.ticks(start,stop,count)」;:862,搜「[-20,0,20,40,60]」;:865,搜「Parameters are mere suggestions」)。 ↩ -
出处:「Working with Data」第 867–874 段(
text/14-ch07-chapter-7-working-with-data.txt:869,搜「tickStep」;:874,搜「[-40, -20, 0, 20, 40, 60, 80]」)。 ↩ -
出处:「Working with Data」第 884–937 段(
text/14-ch07-chapter-7-working-with-data.txt:888,搜「17 functions」;:897,搜「randomNormal(μ,σ)」;:931,搜「17 generators」)。 ↩ ↩2 -
出处:「Working with Data」第 944–965 段(
text/14-ch07-chapter-7-working-with-data.txt:944,搜「randomLcg(seed)」;:962,搜「28, 43, 3, 22, 35」)。 ↩ -
出处:「Working with Data」第 967–990 段(
text/14-ch07-chapter-7-working-with-data.txt:972,搜「Fisher-Yates」;:987,搜「9,4,7,8,6,2,5,1,3」)。 ↩ -
出处:「Working with Data」第 992–997 段(
text/14-ch07-chapter-7-working-with-data.txt:993,搜「generates intermediate values」;:995,搜「behind the scenes」)。 ↩ -
出处:「Working with Data」第 999–1021 段(
text/14-ch07-chapter-7-working-with-data.txt:1001,搜「d3.interpolate(a,b)」;:1017,搜「d3.quantize(interpolator,n)」;:1019,搜「d3.piecewise」)。 ↩ -
出处:「Working with Data」第 1064–1066 段(
text/14-ch07-chapter-7-working-with-data.txt:1065,搜「Chapter 10 covers color interpolation」)。 ↩ -
出处:「Working with Data」第 1067–1096 段(
text/14-ch07-chapter-7-working-with-data.txt:1074,搜「d3.blur(array,radius)」;:1089,搜「[0,100,0,-100,0,100]」;:1093,搜「31.3, 23.5, 1.6」)。 ↩ ↩2 -
出处:「Working with Data」第 1099–1123 段(
text/14-ch07-chapter-7-working-with-data.txt:1105,搜「blur2({data: imageData」;:1115,搜「getImageData」)。 ↩ -
出处:「Working with Data」第 1126–1130 段(
text/14-ch07-chapter-7-working-with-data.txt:1128,搜「Temporal API」;:1129,搜「d3-time module」)。 ↩ -
出处:「Working with Data」第 1194–1210 段(
text/14-ch07-chapter-7-working-with-data.txt:1198,搜「2024-10-18T18:00:00Z」;:1201,搜「Oct 19, 00:00」;:1210,搜「same as d3.timeDay.floor」)。 ↩ -
出处:「Working with Data」第 1217–1228 段(
text/14-ch07-chapter-7-working-with-data.txt:1222,搜「timeWednesday」;:1226,搜「hours since beginning of the year」)。 ↩ -
出处:「Working with Data」第 1206–1207 与 1224 段(
text/14-ch07-chapter-7-working-with-data.txt:1206,搜「local time」;:1224,搜「but not daylight savings time」)。 ↩ ↩2 -
出处:「Working with Data」第 1268–1276 段(
text/14-ch07-chapter-7-working-with-data.txt:1268,搜「What are bins?」;:1272,搜「data compression」)。 ↩ -
出处:「Working with Data」第 1280–1285 段(
text/14-ch07-chapter-7-working-with-data.txt:1283,搜「none of these patterns is apparent」;:1284,搜「simply experimenting」)。 ↩ ↩2 -
出处:「Working with Data」第 1384–1436 段(
text/14-ch07-chapter-7-working-with-data.txt:1394,搜「randomNormal(100, 15)」;:1399,搜「thresholds(100)」;:1401,搜「more than 100 bins」;:1410,搜「scaleBand()」;:1420,搜「darkgreen」;:1424,搜「selectAll("rect.bins")」;:1430,搜「scaleY(0) - scaleY(d.length)」)。 ↩ -
出处:「Working with Data」第 1352–1380 段(
text/14-ch07-chapter-7-working-with-data.txt:1357,搜「d.diameterKm」;:1363,搜「thresholds(3)」;:1368,搜「[0,5,7,10]」;:1376,搜「quantile(data, .25)」)。 ↩ -
出处:「Working with Data」第 1477–1520 段(
text/14-ch07-chapter-7-working-with-data.txt:1483,搜「Year,Jan,Feb,Mar」;:1498,搜「makeTidyRow」;:1509,搜「408 rows」;:1519,搜「Chapter 12」)。 ↩ ↩2 -
出处:「Working with Data」第 1522–1556 段(
text/14-ch07-chapter-7-working-with-data.txt:1529,搜「d3.group(iterable,…keys)」;:1537,搜「throws an exception」;:1542,搜「d3.rollup(iterable,reduce」)。函数表照原书 Table 7.24 转写。 ↩ -
出处:「Working with Data」第 1571–1703 段(
text/14-ch07-chapter-7-working-with-data.txt:1575,搜「yearMap = d3.group」;:1596,搜「yearMonMap = d3.group」;:1608,搜「idxMap = d3.index」;:1614,搜「yearArr = d3.groups」;:1647,搜「yearMonArr[28][1][8][1][0]」;:1649,搜「maps are better for selecting specific items」;:1657,搜「valueMap = d3.rollup」;:1689,搜「d3.flatRollup」)。 ↩ ↩2 -
出处:「Working with Data」第 1704–1712 段(
text/14-ch07-chapter-7-working-with-data.txt:1709,搜「groupSort」)。 ↩ -
出处:「Working with Data」第 1715–1728 段(
text/14-ch07-chapter-7-working-with-data.txt:1715,搜「heatmap table」;:1719,搜「the data will require grouping」)。 ↩ -
出处:「Working with Data」第 1723–1724 段(
text/14-ch07-chapter-7-working-with-data.txt:1723,搜「make it responsive」)。 ↩