使用 d3.max 和 d3.min 函数在数据集中查找最小值和最大值 & 使用动态比例

97 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的26天,点击查看活动详情

使用 d3.max 和 d3.min 函数在数据集中查找最小值和最大值

介绍

D3 的 domain()range() 方法根据数据设置比例尺的信息。 下面有几种更简单的方法。

通常当你设置域的时候,你会想用数据集中的最小值和最大值。 试图手动的找到这些值,尤其是在很大的数据集中,可能会出错。

D3 有两个方法——min()max() 来返回这些值。 下面是一个例子:

const exampleData = [34, 234, 73, 90, 6, 52];
d3.min(exampleData)
d3.max(exampleData)

像在散点图的例子中的 [x, y] 坐标对一样,数据集有可能嵌套数组。 在这种情况下,你需要告诉 D3 怎么计算最大值和最小值。 幸运的是,min()max() 都可以使用回调函数。 在下面这个例子中,回调函数的参数 d 是当前的内部数组。 回调函数需要从内数组中返回你想比较大小的元素(x 值或 y 值)。 下面是一个如何找到二维数组的最大值和最小值的例子:

const locationData = [[1, 7],[6, 3],[8, 3]];
const minX = d3.min(locationData, (d) => d[0]);

minX 的值应为 1

实操

positionData 数组的子数组元素为 x、y 和 z 坐标。 使用 D3 方法从数组中查找 z 坐标(第三个值)的最大值,并将其保存在 output 变量中。

  1. h2 文本应为 8
  2. 应使用 max() 方法。
<body>
  <script>
    const positionData = [[1, 7, -4],[6, 3, 8],[2, 9, 3]]

    const output = d3.max(positionData,d=>d[2]);

    d3.select("body")
      .append("h2")
      .text(output)
  </script>
</body>

使用动态比例

介绍

D3 的 min()max() 方法在设置比例尺时十分有用。

对于一个复杂的数据集,首要是设置比例尺,这样可视化才能适合 SVG 容器的宽和高。 所有数据都应布局在 SVG 画布内部,这样它们在页面上才是可见的。

下面这个例子为散点图设置了 x 轴的比例尺。 domain() 方法给比例尺传递关于散点图原数据值的信息, range() 方法给出在页面上进行可视化的实际空间信息。

在这个例子中,domain 是从 0 到数据集中的最大值, 它使用 max() 方法和基于数组中 x 值的回调函数。 Range 使用 SVG 画布的宽(w),并包含 padding, 这将在散点图和 SVG 画布边缘之间添加空隙。

const dataset = [
  [ 34,    78 ],
  [ 109,   280 ],
  [ 310,   120 ],
  [ 79,    411 ],
  [ 420,   220 ],
  [ 233,   145 ],
  [ 333,   96 ],
  [ 222,   333 ],
  [ 78,    320 ],
  [ 21,    123 ]
];
const w = 500;
const h = 500;

const padding = 30;
const xScale = d3.scaleLinear()
  .domain([0, d3.max(dataset, (d) => d[0])])
  .range([padding, w - padding]);

在一开始可能很难理解 padding。 想象 x 轴是一条从 0 到 500 (SVG 画布宽的值)的水平直线。 在 range() 方法中包含 padding 使散点图沿着这条直线从 30 (而不是 0)开始,在 470 (而不是 500)结束。

实操

使用 yScale 变量创建一个线性的 y 轴比例尺。 domain 应该从 0 开始到数据集中 y 的最大值, range 应该使用 SVG 的高(h),并包含 padding。

注意: 记得保持绘图在右上角。 当你为 y 坐标设置 range 时,大的值(height 减去 padding)是第一个参数,小的值是第二个参数。

  1. h2 的文本应为 30
  2. yScale 的 domain() 应该等于 [0, 411]
  3. yScale 的 range() 应该等于 [470, 30]
<body>
  <script>
    const dataset = [                  [ 34,    78 ],
                  [ 109,   280 ],
                  [ 310,   120 ],
                  [ 79,    411 ],
                  [ 420,   220 ],
                  [ 233,   145 ],
                  [ 333,   96 ],
                  [ 222,   333 ],
                  [ 78,    320 ],
                  [ 21,    123 ]
                ];

    const w = 500;
    const h = 500;

    // 画布边线和图表之间的 padding
    const padding = 30;

    // 创建 x 和 y 轴

    const xScale = d3.scaleLinear()
                    .domain([0, d3.max(dataset, (d) => d[0])])
                    .range([padding, w - padding]);

    const yScale = d3.scaleLinear()
                    .domain([0,d3.max(dataset,d=>d[1])])
                    .range([h - padding,padding])

    const output = yScale(411); // 返回 30
    d3.select("body")
      .append("h2")
      .text(output)
  </script>
</body>