可视化
Owl 是一个 OCaml 数值库。除了对矩阵操作提供广泛支持之外,它还具有灵活的绘图模块。Owl 的 Plot
模块旨在通过最小的编码工作帮助您创建相当复杂的图。它构建在 [Plplot 之上,但将其复杂性隐藏在用户视野之外。
由于 Plplot
调用底层图形设备驱动程序进行绘图,该模块是跨平台的。然而,根据我们的经验,Cairo 包 提供了最高质量和最准确的图形,因此我们建议安装 Cairo。实际上,本教程中的示例都是使用 Cairo PNG 驱动程序
生成的,但正如您将看到的,您可以对图形拥有完全控制,并以多种方式配置它们。
在下面的部分中,我们将通过示例演示在 Owl 中如何使用绘图模块来辅助您完成数据可视化和分析中的多项任务。
创建图
让我们从使用 Plot.create
函数创建图的标准方式开始。以下是其在 Owl_plot.mli
中的类型定义:
val create : ?m:int -> ?n:int -> string -> handle
这是一个例子。
let f x = Maths.sin x /. x in
let h = Plot.create "plot_001.png" in
Plot.set_title h "Function: f(x) = sine x / x";
Plot.set_xlabel h "x-axis";
Plot.set_ylabel h "y-axis";
Plot.set_font_size h 8.;
Plot.set_pen_size h 3.;
Plot.plot_fun ~h f 1. 15.;
Plot.output h
>- : unit = ()
对于任何图形,我们需要通过调用 create
函数获得一个句柄 h
。图像的类型可以从图形文件名中自动推断出来。在这种情况下,我们想创建一个绘制正弦函数的 PNG 图像。我们可以使用 plot_fun
函数实现这一点。此外,我们还设置了 x 和 y 轴标签以及图形标题,以及字体和线条大小。您会发现,这些命令与其他绘图工具(如 Matplotlib)中的命令相似。一旦调用了 Plot.output
,图形就会被“封存”并写入最终文件。生成的图形如下所示。

如果这对您来说看起来太基本了,那么我们在下一部分中有一些花哨的 3D 网格图。
规格
对于 Owl 中的大多数高级绘图函数,都有一个名为 spec
的可选参数。 spec
参数接受一个规格列表,让您更精细地控制图的外观。每个函数都有一组略有不同的参数。如果您传递了某个函数无法理解的参数,它们将被简单地忽略。如果您多次传递相同的参数,则只有最后一个参数会生效。
接下来,我们将提供一些示例,以显示如何使用 spec
参数来更好地调整 Owl 的图。第一个示例展示了如何使用 ZLine
、Contour
和其他 spec
参数配置 mesh
图。
let x, y = Mat.meshgrid (-2.5) 2.5 (-2.5) 2.5 50 50 in
let z = Mat.(sin ((x * x) + (y * y))) in
let h = Plot.create ~m:2 ~n:3 "plot_020.png" in
Plot.subplot h 0 0;
Plot.(mesh ~h ~spec:[ ZLine XY ] x y z);
Plot.subplot h 0 1;
Plot.(mesh ~h ~spec:[ ZLine X ] x y z);
Plot.subplot h 0 2;
Plot.(mesh ~h ~spec:[ ZLine Y ] x y z);
Plot.subplot h 1 0;
Plot.(mesh ~h ~spec:[ ZLine Y; NoMagColor ] x y z);
Plot.subplot h 1 1;
Plot.(mesh ~h ~spec:[ ZLine Y; Contour ] x y z);
Plot.subplot h 1 2;
Plot.(mesh ~h ~spec:[ ZLine XY; Curtain ] x y z);
Plot.output h
>- : unit = ()

第二个示例展示了如何在绘制 3D 表面时调整 surf
绘图函数。
let x, y = Mat.meshgrid (-1.) 1. (-1.) 1. 50 50 in
let z = Mat.(tanh ((x * x) + (y * y))) in
let h = Plot.create ~m:2 ~n:3 "plot_021.png" in
Plot.subplot h 0 0;
Plot.(surf ~h ~spec:[ ] x y z);
Plot.subplot h 0 1;
Plot.(surf ~h ~spec:[ Faceted ] x y z);
Plot.subplot h 0 2;
Plot.(surf ~h ~spec:[ NoMagColor ] x y z);
Plot.subplot h 1 0;
Plot.(surf ~h ~spec:[ Contour ] x y z);
Plot.subplot h 1 1;
Plot.(surf ~h ~spec:[ Curtain ] x y z);
Plot.subplot h 1 2;
Plot.(surf ~h ~spec:[ Altitude 10.; Azimuth 125. ] x y z);
Plot.output h
>- : unit = ()

子图
您可能已经在上一个示例中发现了另一个功能:子图。的确,通过改变 create
函数中 m
和 n
参数的数量,您可以改变子图布局的行数和列数。
let f p i = match i with
| 0 -> Stats.gaussian_rvs ~mu:0. ~sigma:0.5 +. p.(1)
| _ -> Stats.gaussian_rvs ~mu:0. ~sigma:0.1 *. p.(0)
in
let y = Stats.gibbs_sampling f [|0.1;0.1|] 5_000 |> Mat.of_arrays in
let h = Plot.create ~m:2 ~n:2 "plot_002.png" in
Plot.set_background_color h 255 255 255;
(* focus on the subplot at 0,0 *)
Plot.subplot h 0 0;
Plot.set_title h "Bivariate model";
Plot.scatter ~h (Mat.col y 0) (Mat.col y 1);
(* focus on the subplot at 0,1 *)
Plot.subplot h 0 1;
Plot.set_title h "Distribution of y";
Plot.set_xlabel h "y";
Plot.set_ylabel h "Frequency";
Plot.histogram ~h ~bin:50 (Mat.col y 1);
(* focus on the subplot at 1,0 *)
Plot.subplot h 1 0;
Plot.set_title h "Distribution of x";
Plot.set_ylabel h "Frequency";
Plot.histogram ~h ~bin:50 (Mat.col y 0);
(* focus on the subplot at 1,1 *)
Plot.subplot h 1 1;
Plot.set_foreground_color h 255 0 0;
Plot.set_title h "Sine function";
Plot.(plot_fun ~h ~spec:[ LineStyle 2 ] Maths.sin 0. 28.);
Plot.autocorr ~h (Mat.sequential 1 28);
(* output your final plot *)
Plot.output h
>- : unit = ()

多条线
当然,您可以在同一页上绘制多条线(或其他类型的图)。以下是一个在同一个图中绘制正弦和余弦线的示例。
let h = Plot.create "plot_024.png" in
Plot.(plot_fun ~h ~spec:[ RGB (0,0,255); Marker "#[0x2299]"; MarkerSize 8. ] Maths.sin 0. 9.);
Plot.(plot_fun ~h ~spec:[ RGB (255,0,0); Marker "#[0x0394]"; MarkerSize 8. ] Maths.cos 0. 9.);
Plot.legend_on h [|"正弦函数"; "余弦函数"|];
Plot.output h
>- : unit = ()

这里是另一个示例,其中在同一图中既有直方图又有线图。
(* 生成数据 *)
let g x = (Stats.gaussian_pdf x ~mu:0. ~sigma:1.) *. 100. in
let y = Mat.gaussian ~mu:0. ~sigma:1. 1 1000 in
(* 绘制多个数据集 *)
let h = Plot.create "plot_025.png" in
Plot.set_background_color h 255 255 255;
Plot.(histogram ~h ~spec:[ RGB (255,0,50) ] ~bin:100 y);
Plot.(plot_fun ~h ~spec:[ RGB (0,0,255); LineWidth 2. ] g (-4.) 4.);
Plot.legend_on h [|"数据"; "模型"|];
Plot.output h
>- : unit = ()

因此,只要在调用 Plot.output
之前“保持”绘图,您就可以在同一图中绘制许多数据集。
图例
通过分别调用 Plot.legend_on
和 Plot.legend_off
,可以打开和关闭图例。调用 Plot.legend_on
时,您还需要提供一个图例名称数组和图例的位置。在 Plot
中有八个默认位置:
type legend_position =
North | South | West | East | NorthWest | NorthEast | SouthWest | SouthEast
尽管它看起来很混乱,但以下示例显示了如何在 Owl 的绘图模块中使用图例。
(* 生成数据 *)
let x = Mat.(uniform 1 20 *$ 10.) in
let y = Mat.(uniform 1 20) in
let z = Mat.gaussian 1 20 in
(* 绘制多个数据集 *)
let h = Plot.create "plot_026.png" in
Plot.(plot_fun ~h ~spec:[ RGB (0,0,255); LineStyle 1; Marker "*" ] Maths.sin 1. 8.);
Plot.(plot_fun ~h ~spec:[ RGB (0,255,0); LineStyle 2; Marker "+" ] Maths.cos 1. 8.);
Plot.scatter ~h x y;
Plot.stem ~h x z;
let u = Mat.(abs(gaussian 1 10 *$ 0.3)) in
Plot.(bar ~h ~spec:[ RGB (255,255,0); FillPattern 3 ] u);
let v = Mat.(neg u *$ 0.3) in
let u = Mat.sequential 1 10 in
Plot.(area ~h ~spec:[ RGB (0,255,0); FillPattern 4 ] u v);
(* 设置图例 *)
Plot.(legend_on h ~position:NorthEast [|"测试 1"; "测试 2"; "散点"; "柱状"; "直方图"; "区域"|]);
Plot.output h
>- : unit = ()

绘制图案
绘图模块支持多种线型,如下所示:
let h = Plot.create "plot_004.png" in
Plot.set_background_color h 255 255 255;
Plot.set_pen_size h 2.;
Plot.(draw_line ~h ~spec:[ LineStyle 1 ] 1. 1. 9. 1.);
Plot.(draw_line ~h ~spec:[ LineStyle 2 ] 1. 2. 9. 2.);
Plot.(draw_line ~h ~spec:[ LineStyle 3 ] 1. 3. 9. 3.);
Plot.(draw_line ~h ~spec:[ LineStyle 4 ] 1. 4. 9. 4.);
Plot.(draw_line ~h ~spec:[ LineStyle 5 ] 1. 5. 9. 5.);
Plot.(draw_line ~h ~spec:[ LineStyle 6 ] 1. 6. 9. 6.);
Plot.(draw_line ~h ~spec:[ LineStyle 7 ] 1. 7. 9. 7.);
Plot.(draw_line ~h ~spec:[ LineStyle 8 ] 1. 8. 9. 8.);
Plot.set_xrange h 0. 10.;
Plot.set_yrange h 0. 9.;
Plot.output h
>- : unit = ()

同样,我们还可以使用不同的图案填充矩形,如下例所示。
let h = Plot.create "plot_005.png" in
Array.init 9 (fun i ->
let x0, y0 = 0.5, float_of_int i +. 1.0 in
let x1, y1 = 4.5, float_of_int i +. 0.5 in
Plot.(draw_rect ~h ~spec:[ FillPattern i ] x0 y0 x1 y1);
Plot.(text ~h ~spec:[ RGB (0,255,0) ] 2.3 (y0-.0.2) ("pattern: " ^ (string_of_int i)))
) |> ignore;
Plot.output h
>- : unit = ()

折线图
在了解了这些绘图元素之后,在本章的其余部分中,我们将演示一些支持的不同类型的绘图。折线图是最基本的功能。您可以在函数中指定颜色、标记和线型。
let x = Mat.linspace 0. 2. 100 in
let y0 = Mat.sigmoid x in
let y1 = Mat.map Maths.sin x in
let h = Plot.create "plot_022.png" in
Plot.(plot ~h ~spec:[ RGB (255,0,0); LineStyle 1; Marker "#[0x2299]"; MarkerSize 8. ] x y0);
Plot.(plot ~h ~spec:[ RGB (0,255,0); LineStyle 2; Marker "#[0x0394]"; MarkerSize 8. ] x y1);
Plot.(legend_on h ~position:SouthEast [|"sigmoid"; "sine"|]);
Plot.output h
>- : unit = ()

散点图
接下来是散点图。与折线图类似,您可以指定标记类型和标记大小。下面的示例实际上显示了各种标记的模式。它们由不同的 id 引用。
let x = Mat.uniform 1 30 in
let y = Mat.uniform 1 30 in
let h = Plot.create ~m:3 ~n:3 "plot_006.png" in
Plot.set_background_color h 255 255 255;
Plot.subplot h 0 0;
Plot.(scatter ~h ~spec:[ Marker "#[0x2295]"; MarkerSize 5. ] x y);
Plot.subplot h 0 1;
Plot.(scatter ~h ~spec:[ Marker "#[0x229a]"; MarkerSize 5. ] x y);
Plot.subplot h 0 2;
Plot.(scatter ~h ~spec:[ Marker "#[0x2206]"; MarkerSize 5. ] x y);
Plot.subplot h 1 0;
Plot.(scatter ~h ~spec:[ Marker "#[0x229e]"; MarkerSize 5. ] x y);
Plot.subplot h 1 1;
Plot.(scatter ~h ~spec:[ Marker "#[0x2217]"; MarkerSize 5. ] x y);
Plot.subplot h 1 2;
Plot.(scatter ~h ~spec:[ Marker "#[0x2296]"; MarkerSize 5. ] x y);
Plot.subplot h 2 0;
Plot.(scatter ~h ~spec:[ Marker "#[0x2666]"; MarkerSize 5. ] x y);
Plot.subplot h 2 1;
Plot.(scatter ~h ~spec:[ Marker "#[0x22a1]"; MarkerSize 5. ] x y);
Plot.subplot h 2 2;
Plot.(scatter ~h ~spec:[ Marker "#[0x22b9]"; MarkerSize 5. ] x y);
Plot.output h
>- : unit = ()

阶梯图
阶梯图也称为“阶梯图”,因为它以类似阶梯的曲线绘制给定 ndarray 中的元素。
let x = Mat.linspace 0. 6.5 20 in
let y = Mat.map Maths.sin x in
let h = Plot.create ~m:1 ~n:2 "plot_007.png" in
Plot.set_background_color h 255 255 255;
Plot.subplot h 0 0;
Plot.plot_fun ~h Maths.sin 0. 6.5;
Plot.(stairs ~h ~spec:[ RGB (0,128,255) ] x y);
Plot.subplot h 0 1;
Plot.(plot ~h ~spec:[ RGB (0,0,0) ] x y);
Plot.(stairs ~h ~spec:[ RGB (0,128,255) ] x y);
Plot.output h
>- : unit = ()

箱线图
箱线图通过四分位数图形地展示数值数据的分组。它常用于描述统计学。
let y1 = Mat.uniform 1 10 in
let y2 = Mat.uniform 10 100 in
let h = Plot.create ~m:1 ~n:2 "plot_008.png" in
Plot.subplot h 0 0;
Plot.(bar ~h ~spec:[ RGB (0,153,51); FillPattern 3 ] y1);
Plot.subplot h 0 1;
Plot.(boxplot ~h ~spec:[ RGB (0,153,51) ] y2);
Plot.output h
>- : unit = ()

茎叶图
茎叶图很简单,如下代码所示。
let x = Mat.linspace 0.5 2.5 25 in
let y = Mat.map (Stats.exponential_pdf ~lambda:0.1) x in
let h = Plot.create ~m:1 ~n:2 "plot_009.png" in
Plot.set_background_color h 255 255 255;
Plot.subplot h 0 0;
Plot.set_foreground_color h 0 0 0;
Plot.stem ~h x y;
Plot.subplot h 0 1;
Plot.(stem ~h ~spec:[ Marker "#[0x2295]"; MarkerSize 5.; LineStyle 1 ] x y);
Plot.output h
>- : unit = ()

茎叶图常用于显示变量的自相关性,因此 Plot 模块已经包含了方便的 autocorr
。
let x = Mat.linspace 0. 8. 30 in
let y0 = Mat.map Maths.sin x in
let y1 = Mat.uniform 1 30 in
let h = Plot.create ~m:1 ~n:2 "plot_010.png" in
Plot.subplot h 0 0;
Plot.set_title h "Sine";
Plot.autocorr ~h y0;
Plot.subplot h 0 1;
Plot.set_title h "Gaussian";
Plot.autocorr ~h y1;
Plot.output h
>- : unit = ()

面积图
面积图类似于线图,但它填充了线和 x 轴之间的空间,如下所示。
let x = Mat.linspace 0. 8. 100 in
let y = Mat.map Maths.atan x in
let h = Plot.create ~m:1 ~n:2 "plot_011.png" in
Plot.subplot h 0 0;
Plot.(area ~h ~spec:[ FillPattern 1 ] x y);
let x = Mat.linspace 0. (2. *. 3.1416) 100 in
let y = Mat.map Maths.sin x in
Plot.subplot h 0 1;
Plot.(area ~h ~spec:[ FillPattern 2 ] x y);
Plot.output h
>- : unit = ()

直方图和累积分布函数图
直方图是数据可视化中最常用的图之一。给定一系列测量值,您可以使用 histogram
和 ecdf
绘图函数轻松绘制数据的直方图和经验累积分布。
let x = Mat.gaussian 200 1 in
let h = Plot.create ~m:1 ~n:2 "plot_012.png" in
Plot.subplot h 0 0;
Plot.set_title h "直方图";
Plot.histogram ~h ~bin:25 x;
Plot.subplot h 0 1;
Plot.set_title h "经验累积分布函数";
Plot.ecdf ~h x;
Plot.output h
>- : unit = ()

对数图
在 Owl 绘图中,您可以选择在 x 轴和/或 y 轴上使用对数刻度。
let x = Mat.logspace (-1.5) 2. 50 in
let y = Mat.map Maths.exp x in
let h = Plot.create ~m:2 ~n:2 "plot_013.png" in
Plot.subplot h 0 0;
Plot.set_xlabel h "Input Data X";
Plot.set_ylabel h "Input Data Y";
Plot.(loglog ~h ~spec:[ RGB (0,255,0); LineStyle 2; Marker "+" ] ~x:x y);
Plot.subplot h 0 1;
Plot.set_xlabel h "Index of Input Data Y";
Plot.set_ylabel h "Input Data Y";
Plot.(loglog ~h ~spec:[ RGB (0,0,255); LineStyle 1; Marker "*" ] y);
Plot.subplot h 1 0;
Plot.set_xlabel h "Input Data X";
Plot.set_ylabel h "Input Data Y";
Plot.semilogx ~h ~x:x y;
Plot.subplot h 1 1;
Plot.set_xlabel h "Index of Input Data Y";
Plot.set_ylabel h "Input Data Y";
Plot.semilogy ~h y;
Plot.output h
>- : unit = ()

3D图
我们已经看到了上面的3D图的示例。在Plot
模块中有四个与3D图相关的函数。它们是surf
、mesh
、heatmap
和contour
函数。首先,让我们看一下mesh
和surf
函数。
let x, y = Mat.meshgrid (-2.5) 2.5 (-2.5) 2.5 100 100 in
let z0 = Mat.(sin ((x **$ 2.) + (y **$ 2.))) in
let z1 = Mat.(cos ((x **$ 2.) + (y **$ 2.))) in
let h = Plot.create ~m:2 ~n:2 "plot_014.png" in
Plot.subplot h 0 0;
Plot.surf ~h x y z0;
Plot.subplot h 0 1;
Plot.mesh ~h x y z0;
Plot.subplot h 1 0;
Plot.surf ~h x y z1;
Plot.subplot h 1 1;
Plot.mesh ~h x y z1;
Plot.output h
>- : unit = ()

使用altitude
和azimuth
参数轻松控制视角。下面是一个例子。
let x, y = Mat.meshgrid (-2.5) 2.5 (-2.5) 2.5 100 100 in
let z = Mat.(sin ((x * x) + (y * y))) in
let h = Plot.create ~m:1 ~n:3 "plot_015.png" in
Plot.subplot h 0 0;
Plot.(mesh ~h ~spec:[ Altitude 50.; Azimuth 120. ] x y z);
Plot.subplot h 0 1;
Plot.(mesh ~h ~spec:[ Altitude 65.; Azimuth 120. ] x y z);
Plot.subplot h 0 2;
Plot.(mesh ~h ~spec:[ Altitude 80.; Azimuth 120. ] x y z);
Plot.output h
>- : unit = ()
生成的图如下所示。

这里是另一个类似的例子,使用不同的函数。
let x, y = Mat.meshgrid (-3.) 3. (-3.) 3. 50 50 in
let z = Mat.(
3. $* ((1. $- x) **$ 2.) * exp (neg (x **$ 2.) - ((y +$ 1.) **$ 2.)) -
(10. $* (x /$ 5. - (x **$ 3.) - (y **$ 5.)) * (exp (neg (x **$ 2.) - (y **$ 2.)))) -
((1./.3.) $* exp (neg ((x +$ 1.) **$ 2.) - (y **$ 2.)))
)
in
let h = Plot.create ~m:2 ~n:3 "plot_016.png" in
Plot.subplot h 0 0;
Plot.surf ~h x y z;
Plot.subplot h 0 1;
Plot.mesh ~h x y z;
Plot.subplot h 0 2;
Plot.(surf ~h ~spec:[ Contour ] x y z);
Plot.subplot h 1 0;
Plot.(mesh ~h ~spec:[ Contour; Azimuth 115.; NoMagColor ] x y z);
Plot.subplot h 1 1;
Plot.(mesh ~h ~spec:[ Azimuth 115.; ZLine X; NoMagColor; RGB (61,129,255) ] x y z);
Plot.subplot h 1 2;
Plot.(mesh ~h ~spec:[ Azimuth 115.; ZLine Y; NoMagColor; RGB (130,255,40) ] x y z);
Plot.output h
>- : unit = ()

热图和等高线图
最后,让我们看一下使用与之前相同的函数的热图和等高线图的外观。
let x, y = Mat.meshgrid (-3.) 3. (-3.) 3. 100 100 in
let z = Mat.(
3. $* ((1. $- x) **$ 2.) * exp (neg (x **$ 2.) - ((y +$ 1.) **$ 2.)) -
(10. $* (x /$ 5. - (x **$ 3.) - (y **$ 5.)) * (exp (neg (x **$ 2.) - (y **$ 2.)))) -
((1./.3.) $* exp (neg ((x +$ 1.) **$ 2.) - (y **$ 2.)))
)
in
let h = Plot.create ~m:2 ~n:2 "plot_017.png" in
Plot.subplot h 0 0;
Plot.(mesh ~h ~spec:[ Contour ] x y z);
Plot.subplot h 0 1;
Plot.heatmap ~h x y z;
Plot.subplot h 1 0;
Plot.mesh ~h x y z;
Plot.subplot h 1 1;
Plot.contour ~h x y z;
Plot.output h
>- : unit = ()

高级统计图
除了这些常用的基本图类型外,我们还支持几种高级统计图。例如,qqplot
和probplot
都是用于确定数据集是否来自某个特定分布的简单图形测试。
qqplot
显示样本数据y的分位数与给定分布的理论分位数值,或样本数据x的分位数的量子-量子图。以下是一个例子。
let y = Mat.(gaussian 100 1 *$ 10.) in
let x = Mat.gaussian 200 1 in
let h = Plot.create ~m:2 ~n:2 "plot_018.png" in
Plot.subplot h 0 0;
Plot.set_title h "Gaussian vs. Gaussian Sample";
Plot.set_ylabel h "Quantiles of Input Sample";
Plot.set_xlabel h "Normal Distribution Quantiles";
Plot.qqplot ~h y ~x:x;
Plot.subplot h 0 1;
Plot.set_title h "Gaussian vs. Default Dist";
Plot.set_ylabel h "Quantiles of Input Sample";
Plot.set_xlabel h "Normal Distribution Quantiles";
Plot.(qqplot ~h y ~spec:[RGB (0,128,255)]);
Plot.subplot h 1 0;
Plot.set_title h "Gaussian vs. Rayleigh Dist";
Plot.set_ylabel h "Quantiles of Input Sample";
Plot.set_xlabel h "Rayleigh Distribution (sigma=0.5) Quantiles";
Plot.qqplot ~h y ~pd:(fun p -> Stats.rayleigh_ppf p 0.5);
Plot.subplot h 1 1;
Plot.set_title h "Gaussian vs. Chi-Square Dist";
Plot.set_ylabel h "Quantiles of Input Sample";
Plot.set_xlabel h "Chi-Square Distribution (k=10) Quantiles";
Plot.qqplot ~h y ~pd:(fun p -> Stats.chi2_ppf p 10.);
Plot.output h
>- : unit = ()

probplot
类似于qqplot
。它包含两种特殊情况:normplot
用于给定的理论分布为正态分布,以及wblplot
用于威布尔分布。以下是它们的示例。
let x = Mat.empty 200 1 |> Mat.map (fun _ -> Stats.weibull_rvs 1.2 1.5) in
let h = Plot.create ~m:1 ~n:2 "plot_019.png" in
Plot.subplot h 0 0;
Plot.set_title h "随机威布尔样本 vs. 标准正态分布";
Plot.set_xlabel h "样本数据";
Plot.set_ylabel h "理论正态分布";
Plot.normplot ~h x;
Plot.subplot h 0 1;
Plot.set_title h "随机威布尔样本 vs. 威布尔分布";
Plot.set_xlabel h "样本数据";
Plot.set_ylabel h "理论威布尔分布";
Plot.wblplot ~h ~lambda:1.2 ~k:1.5 x;
Plot.output h
>- : unit = ()

摘要
本章介绍了Owl中的绘图模块,包括如何创建、操作绘图,以及支持的不同类型的绘图。本章提供了许多示例,旨在成为您在需要可视化任务时随时查阅的手册。实际上,本书中大多数图表都基于这个模块。
本章的一个潜在问题是,我们可能没有太多考虑“颜色和谐性”。默认选择的颜色可能并不总是令人愉悦。好消息是,您可以轻松更改图表中的颜色。尝试搜索“色彩理论”,您会找到许多指南。例如,在线图中,类似颜色可能是一个不错的选择。这些颜色是12部分色轮上的任何连续三种颜色,如黄绿色、黄色和黄橙色。我们发现可视化的艺术方面通常令人愉悦。