【rust】《Rust深度学习[3]-数据可视化库(Plotters)》

什么是Plotters?

Plotters是一个用纯Rust开发的图形库,用于中渲染图形、图表和数据可视化。它支持静态图片渲染和实时渲染,并支持多种后端,包括:位图格式(png、bmp、gif等)、矢量图(svg)、窗口和HTML5 Canvas。

Plotters对不同后端使用统一的高级API,并允许开发者自定义坐标系。在Plotters中,任何类型的图表都被抽象为一系列绘图操作,通过这些绘图操作,开发者可以自由地操控和组合绘图内容。因此Plotters不会限制图表类型,开发者可以组合出任意内容的图表。

导入依赖库

[dependencies]
plotters = "0.3.3"

折线图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("折线图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
.build_cartesian_2d(0.0..10.0, 0.0..10.0)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 绘制折线
chart.draw_series(LineSeries::new(
// vec![(0., 2.), (1., 1.), (2., 2.), (3., 3.), (4., 4.), (5., 5.), (6., 6.), (7., 7.), (8., 8.), (9., 9.)],
vec![0., 1., 2., 3., 4., 5., 6., 7., 8.].iter().map(|x| (*x, *x)),
// 线条颜色
&BLUE,
))?;
Ok(())
}

多折线图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("多折线图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
.build_cartesian_2d(0.0..10.0, 0.0..10.0)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 绘制多折线图
// 折线1
chart.draw_series(LineSeries::new(
// x.powf(2) 求x的2次幂
(0..10).map(|x| (x as f64, (x as f64).powf(2.0))),
&RED.stroke_width(5).color,
// 标签
))?.label("y=x^2")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
// 折线2
chart.draw_series(LineSeries::new(
(0..10).map(|x| (x as f64, (x as f64).powf(2.0) + 2.0)),
&BLUE.stroke_width(5).color,
// 标签
))?.label("y=x^2+2")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
// 配置标签样式
chart.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
}

散点图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("散点图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
.build_cartesian_2d(0.0..10.0, 0.0..10.0)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 散点位置
let data = [
(1., 2.),
(2., 3.),
(3., 4.),
(4., 5.),
(5., 6.),
];
// 绘制散点
chart.draw_series(
data.iter()
.map(|(x, y)| {
Circle::new((*x, *y), 5, BLUE.filled())
})
.collect::<Vec<_>>(),
)?;
Ok(())
}

多标记散点图

use plotters::prelude::*;
const DATA1: [(i32, i32); 30] = [
(-3, 1), (-2, 3), (4, 2), (3, 0), (6, -5), (3, 11), (6, 0), (2, 14), (3, 9), (14, 7), (8, 11),
(10, 16), (7, 15), (13, 8), (17, 14), (13, 17), (19, 11), (18, 8), (15, 8), (23, 23), (15, 20),
(22, 23), (22, 21), (21, 30), (19, 28), (22, 23), (30, 23), (26, 35), (33, 19), (26, 19)
];
const DATA2: [(i32, i32); 30] = [
(1, 22), (0, 22), (1, 20), (2, 24), (4, 26), (6, 24), (5, 27), (6, 27), (7, 27), (8, 30), (10, 30),
(10, 33), (12, 34), (13, 31), (15, 35), (14, 33), (17, 36), (16, 35), (17, 39), (19, 38), (21, 38),
(22, 39), (23, 43), (24, 44), (24, 46), (26, 47), (27, 48), (26, 49), (28, 47), (28, 50)
];
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("散点图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
.build_cartesian_2d(-10..50, -10..50)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 设置三角形标记散点
chart.draw_series(
DATA1.iter().map(
|point| TriangleMarker::new(*point, 5, &BLUE)
),
)?.label("三角")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));
// 设置圆圈标记散点
chart.draw_series(
DATA2.iter().map(
|point| Circle::new(*point, 5, &RED)
),
)?.label("圆圈")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
// 配置标签样式
chart.configure_series_labels()
.background_style(&WHITE.mix(0.8))
.border_style(&BLACK)
.draw()?;
Ok(())
}

面积图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("面积图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
.build_cartesian_2d(0..10, 0..50)?;
// 配置网格线
chart.configure_mesh().draw()?;
let data = [25, 37, 15, 32, 45, 33, 32, 10, 29, 0, 21];
let temp = (0..).zip(data.iter().map(|x| *x));
println!("{:?}", temp);
chart.draw_series(
// 绘制面积图
AreaSeries::new(
// { a: 0.., b: Map { iter: Iter([25, 37, 15, 32, 45, 33, 32, 10, 29, 0, 21]) } }
// 0.. 顺序x轴
(0..).zip(data.iter().map(|x| *x)),
// 基线
0,
// 透明度
&RED.mix(0.2)
).border_style(&RED) // 最亮边线的样式
)?;
Ok(())
}

柱状图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("柱状图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
// 重点!!!! 这里的传值必须为SegmentedCoord类型
.build_cartesian_2d((0..10).into_segmented(), 0..50)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 数值
let data = [25, 37, 15, 32, 45, 33, 32, 10, 0, 21, 5];
chart.draw_series(
(0..).zip(data.iter()).map(
|(x, y)| {
// 创建x轴底部分段对象
let x0 = SegmentValue::Exact(x);
// 创建x轴顶部分段对象
let x1 = SegmentValue::Exact(x + 1);
let mut bar = Rectangle::new([(x0, 0), (x1, *y)], RED.filled());
// 柱左右间距
bar.set_margin(0, 0, 5, 5);
bar
}
))?;
Ok(())
}

水平柱状图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("水平柱状图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
// 重点!!!! 这里的传值必须为SegmentedCoord类型
.build_cartesian_2d(0..50, (0..10).into_segmented())?;
// 配置网格线
chart.configure_mesh().draw()?;
// 数值
let data = [25, 37, 15, 32, 45, 33, 32, 10, 0, 21, 5];
// y轴
let index = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
chart.draw_series(
// 循环x轴数据
// 压缩y轴生成结构
data.iter().zip(index.iter()).map(
|(x, y)| {
// 创建y轴左部分段对象
let y0 = SegmentValue::Exact(*y);
// 创建y轴右部分段对象
let y1 = SegmentValue::Exact(*y + 1);
let mut bar = Rectangle::new([(0, y0), (*x, y1)], GREEN.filled());
// 设置上下柱间距
bar.set_margin(5, 5, 0, 0);
bar
}
))?;
Ok(())
}

真假柱状图

use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 创建svg图片对象
let root = SVGBackend::new("plot.svg", (640, 480)).into_drawing_area();
// 图片对象的背景颜色填充
root.fill(&WHITE)?;
// 创建绘图对象
let mut chart = ChartBuilder::on(&root)
// 图表名称 (字体样式, 字体大小)
.caption("真假柱状图", ("sans-serif", 30))
// 图表左侧与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Left, 40)
// 图表底部与图片边缘的间距
.set_label_area_size(LabelAreaPosition::Bottom, 40)
// 构建二维图像, x轴 0.0 - 10.0; y轴 0.0 - 10.0;
// 重点!!!! 这里的传值必须为SegmentedCoord类型
.build_cartesian_2d([true, false].into_segmented(), 0..50)?;
// 配置网格线
chart.configure_mesh().draw()?;
// 数值
let prim:Vec<_> = (2..50).map(is_prime).collect();
chart.draw_series(
Histogram::vertical(&chart)
.margin(100)
.data(prim.iter().map(|x| (x, 1)))
)?;
Ok(())
}
fn is_prime(n: i32) -> bool {
for i in 2..n {
if n % i == 0 {
return false;
}
}
true
}

箱式图

use chrono::{Duration, NaiveDate};
use plotters::prelude::*;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 获取股票数据
let data = get_data();
// 创建绘图区域,大小为 1024x768
let root = BitMapBackend::new("stock.png", (1024, 768)).into_drawing_area();
// 填充白色背景
root.fill(&WHITE)?;
// 计算数据的起始和结束日期
let (to_date, from_date) = (
parse_time(data[0].0) + Duration::days(1),
parse_time(data[29].0) - Duration::days(1),
);
// 创建图表构建器
let mut chart = ChartBuilder::on(&root)
.x_label_area_size(40)
.y_label_area_size(40)
.caption("MSFT Stock Price", ("sans-serif", 50.0).into_font())
.build_cartesian_2d(from_date..to_date, 110f32..135f32)?;
// 配置网格样式
chart.configure_mesh().light_line_style(WHITE).draw()?;
// 绘制蜡烛图
chart.draw_series(
data.iter().map(|x| {
CandleStick::new(parse_time(x.0), x.1, x.2, x.3, x.4, GREEN.filled(), RED, 15)
}),
)?;
// 保存图表到文件
root.present().expect("无法将结果写入文件,请确保当前目录下存在该目录");
Ok(())
}
// 解析日期字符串为 NaiveDate 类型
fn parse_time(t: &str) -> NaiveDate {
NaiveDate::parse_from_str(&format!("{} 0:0", t), "%Y-%m-%d %H:%M").unwrap()
}
// 获取股票数据
fn get_data() -> Vec<(&'static str, f32, f32, f32, f32)> {
vec![
("2019-04-25", 130.06, 131.37, 128.83, 129.15),
("2019-04-24", 125.79, 125.85, 124.52, 125.01),
("2019-04-23", 124.1, 125.58, 123.83, 125.44),
("2019-04-22", 122.62, 124.0000, 122.57, 123.76),
("2019-04-18", 122.19, 123.52, 121.3018, 123.37),
("2019-04-17", 121.24, 121.85, 120.54, 121.77),
("2019-04-16", 121.64, 121.65, 120.1, 120.77),
("2019-04-15", 120.94, 121.58, 120.57, 121.05),
("2019-04-12", 120.64, 120.98, 120.37, 120.95),
("2019-04-11", 120.54, 120.85, 119.92, 120.33),
("2019-04-10", 119.76, 120.35, 119.54, 120.19),
("2019-04-09", 118.63, 119.54, 118.58, 119.28),
("2019-04-08", 119.81, 120.02, 118.64, 119.93),
("2019-04-05", 119.39, 120.23, 119.37, 119.89),
("2019-04-04", 120.1, 120.23, 118.38, 119.36),
("2019-04-03", 119.86, 120.43, 119.15, 119.97),
("2019-04-02", 119.06, 119.48, 118.52, 119.19),
("2019-04-01", 118.95, 119.1085, 118.1, 119.02),
("2019-03-29", 118.07, 118.32, 116.96, 117.94),
("2019-03-28", 117.44, 117.58, 116.13, 116.93),
("2019-03-27", 117.875, 118.21, 115.5215, 116.77),
("2019-03-26", 118.62, 118.705, 116.85, 117.91),
("2019-03-25", 116.56, 118.01, 116.3224, 117.66),
("2019-03-22", 119.5, 119.59, 117.04, 117.05),
("2019-03-21", 117.135, 120.82, 117.09, 120.22),
("2019-03-20", 117.39, 118.75, 116.71, 117.52),
("2019-03-19", 118.09, 118.44, 116.99, 117.65),
("2019-03-18", 116.17, 117.61, 116.05, 117.57),
("2019-03-15", 115.34, 117.25, 114.59, 115.91),
("2019-03-14", 114.54, 115.2, 114.33, 114.59),
]
}

 

其他可视化图-参考地址:https://plotters-rs.github.io/book/basic/draw_3d_plots.html

https://github.com/plotters-rs/plotters/tree/master?tab=readme-ov-file

 

部分内容来源:https://jarod.blog.csdn.net/article/details/128126174

本文作者:芋白🥕

本文链接:https://www.cnblogs.com/-CO-/p/18152675

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   芋白  阅读(1141)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
🔑