41、数据可视化的技术与实践

数据可视化的技术与实践

1. 基础计算与函数定义

在数据可视化的过程中,首先需要对数据进行一些基础的计算和处理。假设 w 为 1(即所有五分位数宽度恒定),可以得到一系列方程,这些方程可以用一个简单的递归函数来表示。以下是具体的代码实现:

(defn area-points [proportions]
  (let [f (fn [prev area]
            (-> (- area prev)
                (* 2)
                (+ prev)))
        sum (reduce + proportions)]
    (->> (reductions f (first proportions) proportions)
         (map #(/ % sum)))))

area-points 函数的作用是根据输入的比例数据计算一系列的点,这些点将用于后续的绘图。 reductions 函数与 reduce 类似,但会保留计算的中间步骤,返回一个对应于 y 坐标(比例)高度的序列值。

2. 绘制复杂形状

2.1 基本形状绘制

要绘制复杂形状,可以使用 Quil 库。首先调用 q/begin-shape 表示开始构建一系列顶点,后续调用 q/vertex 来指定顶点,最后调用 q/end-shape 完成形状的绘制。以下是一个绘制测试形状的示例代码:

(defn plot-area [proportions px py width height]
  (let [ys      (area-points proportions)
        points  (map vector (range) ys)
        x-scale (/ width (dec (count ys)))
        y-scale (/ height (apply max ys))]
    (q/stroke 0)
    (q/fill 200)
    (q/begin-shape)
    (doseq [[x y] points]
      (q/vertex (+ px (* x x-scale))
                (- py (* y y-scale))))
      (q/end-shape)))

(defn ex-10-16 []
  (let [expected [3 6.5 12 20 58.5]
        width  640
        height 480
        setup (fn []
                (q/background 255)
                (plot-area expected 0 height width height))]
    (q/sketch :setup setup :size [width height])))

这个示例使用 area-points 函数绘制了 [3 6.5 12 20 58.5] 系列,这是美国财富预期分布数据表中的百分比值系列。然而,这个结果并不理想,因为 Quil 不知道如何封闭形状,只是简单地从最后一个点画一条边回到第一个点,穿过了图表的对角线。

2.2 完整形状绘制

为了解决这个问题,可以在迭代 ys 序列前后添加额外的 q/vertex 调用,确保在调用 q/end-shape 之前完整描述形状。以下是改进后的代码:

(defn plot-full-area [proportions px py width height]
  (let [ys      (area-points proportions)
        points  (map vector (range) ys)
        x-scale (/ width (dec (count ys)))
        y-scale (/ height (apply max ys))]
    (q/stroke 0)
    (q/fill 200)
    (q/begin-shape)
    (q/vertex 0 height)
    (doseq [[x y] points]
      (q/vertex (+ px (* x x-scale))
                (- py (* y y-scale))))
    (q/vertex width height)
    (q/end-shape)))

(defn ex-10-17 []
  (let [expected [3 6.5 12 20 58.5]
        width  640
        height 480
        setup (fn []
                (q/background 255)
                (plot-full-area expected 0 height width height))]
    (q/sketch :setup setup :size [width height])))

改进后的结果更接近面积图。以下是绘制过程的 mermaid 流程图:

graph LR
    A[开始] --> B[计算 ys 和 points]
    B --> C[设置笔触和填充颜色]
    C --> D[开始绘制形状]
    D --> E[添加底部左顶点]
    E --> F[迭代 points 添加顶点]
    F --> G[添加底部右顶点]
    G --> H[结束绘制形状]
    H --> I[结束]

3. 绘制曲线

为了去除面积图中的尖锐角落,可以使用 Quil 的样条曲线。 q/curve-vertex 函数实现了一种称为 Catmull - Rom 样条的曲线绘制方法。要绘制曲线,至少需要指定四个顶点,第一个和最后一个将作为控制点,曲线将在中间两个顶点之间绘制。以下是相关代码:

(defn smooth-curve [xs ys]
  (let [points (map vector xs ys)]
    (apply q/curve-vertex (first points))
    (doseq [point points]
      (apply q/curve-vertex point))
    (apply q/curve-vertex (last points))))

(defn smooth-stroke [xs ys]
  (q/begin-shape)
  (q/vertex (first xs) (first ys))
  (smooth-curve (rest xs) (rest ys))
  (q/end-shape))

(defn smooth-area [xs ys]
  (q/begin-shape)
  (q/vertex (first xs) (first ys))
  (smooth-curve (rest xs) (rest ys))
  (q/vertex (last xs) (first ys))
  (q/end-shape))

(defn plot-curve [xs ys fill-color
                  stroke-color stroke-weight]
  (let [points (map vector xs ys)]
    (q/no-stroke)
    (q/fill fill-color)
    (smooth-area xs ys)
    (q/no-fill)
    (q/stroke stroke-color)
    (q/stroke-weight stroke-weight)
    (smooth-stroke xs ys)))

(defn plot-smooth-area [proportions px py width height]
  (let [ys      (cons 0 (area-points proportions))
        points  (map vector (range) ys)
        x-scale (/ width (dec (count ys)))
        y-scale (/ height (apply max ys) -1)]
    (plot-curve (map (point->px px x-scale) (range (count ys)))
                (map (point->px py y-scale) ys)
                (q/color 200)
                (q/color 0) 2)))

(defn ex-10-18 []
  (let [expected [3 6.5 12 20 58.5]
        width  640
        height 480
        setup (fn []
                (q/background 255)
                (plot-smooth-area expected 0 height
                                  width height))]
    (q/sketch :setup setup :size [width height])))

曲线的效果虽然微妙,但能为图表增添一些精致感。以下是使用曲线绘制的步骤列表:
1. 定义 smooth-curve 函数,添加控制点和中间顶点。
2. 定义 smooth-stroke smooth-area 函数,分别用于绘制线条和填充区域。
3. 定义 plot-curve 函数,结合填充和线条绘制。
4. 定义 plot-smooth-area 函数,使用 plot-curve 函数绘制平滑的面积图。
5. 调用 ex-10-18 函数生成最终的图表。

4. 绘制复合图表

在绘制多个图表时,需要确保它们使用相同的比例,以便进行比较。以下是绘制复合图表的代码:

(defn plot-areas [series px py width height]
  (let [series-ys (map area-points series)
        n-points  (count (first series-ys))
        x-scale   (point->px px (/ width (dec n-points)))
        xs        (map x-scale (range n-points))
        y-max     (apply max (apply concat series-ys))
        y-scale   (point->px py (/ height y-max -1))]
    (doseq [ys series-ys]
      (plot-curve (cons (first xs) xs)
                  (map y-scale (cons 0 ys))
                  (q/color 255 100)
                  (q/color 255 200) 3))))

(defn ex-10-19 []
  (let [expected [3 6.5 12 20 58.5]
        ideal    [10.5 14 21.5 22 32]
        width  640
        height 480
        setup (fn []
                (q/background 100)
                (plot-areas [expected ideal] 0 height
                            width height))]
    (q/sketch :setup setup :size [width height])))

通过 plot-areas 函数,可以绘制多个系列的图表,并确保它们使用相同的比例。以下是绘制复合图表的步骤表格:
| 步骤 | 操作 |
| ---- | ---- |
| 1 | 计算每个系列的 ys 值 |
| 2 | 确定 x 轴的比例和 x 坐标序列 |
| 3 | 找出所有系列中 y 的最大值 |
| 4 | 确定 y 轴的比例 |
| 5 | 遍历每个系列的 ys 值,调用 plot-curve 函数进行绘制 |

5. 输出为 PDF

为了输出高质量的可视化结果,可以将图表输出为 PDF 格式。PDF 格式是基于矢量的,可在任何分辨率下无损缩放。以下是输出为 PDF 的代码:

(defn ex-10-21 []
  (let [size [960 540]]
    (q/sketch :size size
              :setup #((draw-shapes)
                       (draw-expected-ideal)
                       (draw-banknotes)
                       (draw-axis-labels)
                       (draw-title))
              :renderer :pdf
              :output-file "wealth-distribution.pdf")))

通过配置 :renderer :pdf 并指定 :output-file 路径,即可将图表输出为 PDF 文件。以下是输出为 PDF 的操作步骤:
1. 定义图表的大小。
2. 设置 :setup 函数,包含所有需要绘制的元素。
3. 指定 :renderer :pdf
4. 指定 :output-file 为所需的文件名。
5. 调用 q/sketch 函数生成最终的 PDF 文件。

综上所述,通过这些技术和方法,可以实现从简单的形状绘制到复杂的复合图表绘制,并将结果输出为高质量的 PDF 文件,为数据可视化提供了丰富的选择和强大的功能。

6. 数据可视化的应用与效果

数据可视化在实际应用中具有重要的价值,能够将复杂的数据以直观的图表形式呈现出来,帮助人们更好地理解和分析数据。例如,通过面积图和复合图表可以清晰地展示财富分布的预期和理想情况,使人们对数据有更直观的认识。

以下是一个简单的总结表格,展示了不同类型图表的特点和应用场景:
| 图表类型 | 特点 | 应用场景 |
| ---- | ---- | ---- |
| 面积图 | 可以展示数据的累积效果,强调各部分与整体的关系 | 展示财富分布、市场份额等 |
| 曲线图表 | 去除尖锐角落,使图表更美观、平滑 | 用于需要强调趋势的场景,如股票走势等 |
| 复合图表 | 可以同时展示多个系列的数据,便于比较 | 对比不同方案、不同时间段的数据等 |
| PDF 输出 | 矢量格式,可无损缩放,适合打印和高质量展示 | 需要输出高质量报告、文档等 |

6.1 财富分布可视化示例

以财富分布可视化为例,通过前面介绍的方法,可以将美国财富的预期分布、理想分布等数据以直观的图表形式展示出来。以下是一个绘制预期和理想财富分布的复合图表的 mermaid 流程图:

graph LR
    A[开始] --> B[定义预期和理想数据系列]
    B --> C[计算系列的 ys 值]
    C --> D[确定 x 轴和 y 轴的比例]
    D --> E[遍历系列 ys 值]
    E --> F[调用 plot-curve 函数绘制]
    F --> G[设置背景颜色]
    G --> H[调用 q/sketch 生成图表]
    H --> I[结束]

通过这个流程图,可以清晰地看到绘制复合图表的整个过程,从数据准备到最终图表生成。

6.2 可视化效果的提升

在实际应用中,还可以通过一些方法进一步提升可视化的效果。例如,添加额外的数据、调整颜色和透明度、添加标签和标题等。以下是一些具体的操作步骤:
1. 添加额外的数据 :可以在图表中添加更多的数据系列,或者添加一些辅助数据,如平均值、中位数等,以提供更多的信息。
2. 调整颜色和透明度 :选择合适的颜色和透明度可以使图表更加美观和易于区分。例如,在复合图表中,可以使用不同的颜色来表示不同的系列,并调整透明度以避免相互遮挡。
3. 添加标签和标题 :为图表添加清晰的标签和标题可以帮助读者更好地理解图表的含义。例如,在财富分布图表中,可以添加坐标轴标签、系列名称和图表标题等。

7. 总结与展望

7.1 总结

通过前面的介绍,我们了解了数据可视化的多种方法和技术,包括基础的形状绘制、曲线绘制、复合图表绘制以及输出为 PDF 等。这些方法和技术可以帮助我们将复杂的数据以直观、美观的图表形式呈现出来,为数据分析和决策提供有力的支持。

以下是一个简单的技术总结列表:
1. 基础形状绘制 :使用 q/begin-shape q/vertex q/end-shape 函数构建复杂形状。
2. 曲线绘制 :使用 q/curve-vertex 函数实现 Catmull - Rom 样条曲线,去除图表中的尖锐角落。
3. 复合图表绘制 :通过计算统一的比例,确保多个系列的图表具有可比性。
4. PDF 输出 :配置 :renderer :pdf 并指定 :output-file 路径,将图表输出为高质量的 PDF 文件。

7.2 展望

数据可视化是一个不断发展的领域,未来还有许多可以探索和改进的地方。例如,可以进一步研究更复杂的曲线绘制方法,以实现更精确的趋势展示;可以开发更多的交互功能,使图表更加动态和灵活;还可以结合机器学习和人工智能技术,实现自动化的数据可视化。

总之,数据可视化在数据分析和决策中具有重要的作用,通过不断学习和实践,可以掌握更多的技术和方法,为数据可视化带来更多的可能性。希望本文介绍的内容能够为读者在数据可视化方面提供一些帮助和启发。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值