真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

Rust機器學(xué)習(xí)之Plotters-創(chuàng)新互聯(lián)

Rust機器學(xué)習(xí)之Plotters

本文將帶領(lǐng)大家學(xué)習(xí)Plotters的基礎(chǔ)用法。重點學(xué)習(xí)Plotters的圖表元素和常用圖表的使用。

在漢陰等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供成都網(wǎng)站制作、成都做網(wǎng)站 網(wǎng)站設(shè)計制作按需網(wǎng)站設(shè)計,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站制作,營銷型網(wǎng)站,外貿(mào)網(wǎng)站建設(shè),漢陰網(wǎng)站建設(shè)費用合理。

本文是“Rust替代Python進行機器學(xué)習(xí)”系列文章的第四篇,其他教程請參考下面表格目錄:

Python庫Rust替代方案教程
numpyndarrayRust機器學(xué)習(xí)之ndarray
pandasPolarsRust機器學(xué)習(xí)之Polars
scikit-learnLinfaRust機器學(xué)習(xí)之Linfa
matplotlibplottersRust機器學(xué)習(xí)之plotters
pytorchtch-rsRust機器學(xué)習(xí)之tch-rs
networkspetgraphRust機器學(xué)習(xí)之petgraph

數(shù)據(jù)和算法工程師偏愛Jupyter,為了跟Python保持一致的工作環(huán)境,文章中的示例都運行在Jupyter上。因此需要各位搭建Rust交互式編程環(huán)境(讓Rust作為Jupyter的內(nèi)核運行在Jupyter上),相關(guān)教程請參考 Rust交互式編程環(huán)境搭建

文章目錄
    • 什么是Plotters
    • 安裝Plotters
    • Plotters初探
    • 添加圖表元素
      • 添加網(wǎng)格
      • 添加坐標(biāo)軸
      • 添加圖例
    • 常見圖表
      • 散點圖
      • 折線圖
      • 直方圖
      • 多圖組合
    • 結(jié)語

什么是Plotters

Plotters是一個用純Rust開發(fā)的圖形庫,用于中渲染圖形、圖表和數(shù)據(jù)可視化。它支持靜態(tài)圖片渲染和實時渲染,并支持多種后端,包括:位圖格式(png、bmp、gif等)、矢量圖(svg)、窗口和HTML5 Canvas。

Plotters對不同后端使用統(tǒng)一的高級API,并允許開發(fā)者自定義坐標(biāo)系。在Plotters中,任何類型的圖表都被抽象為一系列繪圖操作,通過這些繪圖操作,開發(fā)者可以自由地操控和組合繪圖內(nèi)容。因此Plotters不會限制圖表類型,開發(fā)者可以組合出任意內(nèi)容的圖表。

在這里插入圖片描述

圖1. Plotters圖表案例
安裝Plotters

安裝Plotters非常簡單。如果是Cargo項目,只需要在Cargo.toml中加入

[dependencies]
plotters = "0.3.4"

如果是在jupyter環(huán)境下,可以用evcxr:dep加載依賴,只需要加入下面一句:

:dep plotters = {version = "0.3.4", default_features = false, features = ["evcxr", "all_series", "all_elements"] }

因為evcxr只支持輸出SVG格式圖片,所以這里不需要其他后端,因此我們需要加上default_features = false關(guān)掉plotters原本的后端,同時加上features = ["evcxr", "all_series", "all_elements"],讓plotters支持evcxr環(huán)境,all_series表示支持所有圖表,all_elements表示支持所有的圖表元素。

關(guān)掉plotters原本的后端能讓plotters第一次加載時快很多,但即便這樣,初次編譯plotters還是需要點時間。但好在jupyter中cell之間是共享環(huán)境的,第一次編譯加載完后,后面調(diào)用都很快。

Plotters初探

安裝好plotters后,我們來看一下Plotters的基本用法。

首先需要引入所需的模塊,這里最簡單的做法是引入prelude,prelude里包含了evcxr繪圖所需的evcxr_figure方法。

extern crate plotters;
use plotters::prelude::*;

要想在Jupyter中創(chuàng)建圖表,需要使用evcxr_figure方法。evcxr_figure方法接收2個參數(shù),第一個參數(shù)是圖表的尺寸,第二個參數(shù)是一個閉包,用于處理圖表的繪制。這里的閉包會帶上一個DrawingArea對象,這是plotters的繪圖后端,一切繪圖操作都在此后端上進行。我們先來看個簡單的例子:

evcxr_figure((300, 100), |root| {// 繪圖邏輯
    root.fill(&BLUE)?;
    // 最后返回OK告訴Plotters畫完了
    Ok(())
})

上面的代碼會在Jupyter中顯示一個用綠色填充的300*100大小的矩形。

在這里插入圖片描述

上面的圖形太單調(diào)了,我們在上面寫點文字。

evcxr_figure((300, 100), |root| {// 繪圖邏輯
    root.fill(&GREEN)?;
    // 繪制文字
    root.draw(&Text::new("Plotters真好用!", (40, 40), ("Arial", 30).into_font()))?;
    // 最后返回OK告訴Plotters畫完了
    Ok(())
})

上面的代碼在原來代碼的基礎(chǔ)上加入了一行root.draw(&Text::new("Plotters真好用!", (40, 40), ("Arial", 30).into_font()))?;。這里draw方法用于繪制元素,傳入3個參數(shù),第一個參數(shù)是繪制的內(nèi)容,這里我們創(chuàng)建了一個文本(Text)對象;第二個參數(shù)是繪制的位置(元素左上角在繪圖區(qū)的位置);第三個參數(shù)是字體對象,可以空值文本的字體和大小。繪制效果如下圖:

在這里插入圖片描述

Plotters的一大特性是可以通過將繪圖區(qū)域分割成若干子繪圖區(qū)域來繪制多個圖形,并且這種分割可以遞歸地進行下去。這個特性使得Plotters實現(xiàn)分型繪圖非常簡單。我們嘗試用Plotters畫一個謝爾賓斯基地毯:

use plotters::coord::Shift;

pub fn sierpinski_carpet(
    depth: u32, 
    drawing_area: &DrawingArea) 
->Result<(), Box>{if depth >0 {// 將傳入地繪圖區(qū)分割成3*3個子區(qū)域
        let sub_areas = drawing_area.split_evenly((3,3));
        // 遍歷這3*3個子區(qū)域
        for (idx, sub_area) in (0..).zip(sub_areas.iter()) {if idx == 4 {// 第5個區(qū)域(中心區(qū)域)填上白色
                sub_area.fill(&WHITE)?;
            } else {// 其他區(qū)域遞歸地進行繪圖
                sierpinski_carpet(depth - 1, sub_area)?;
            }
        }
    }
    Ok(())
}

evcxr_figure((4800,4800), |root| {root.fill(&BLACK)?;
    sierpinski_carpet(5, &root)
}).style("width: 400px") // 這里可以CSS來展示輸出圖片在網(wǎng)頁上的顯示

在這里插入圖片描述

除了繪制各種圖形外,Plotters最主要的功能就是繪制圖表。Plotters提供了_圖表上下文_API讓我們可以方便地操作圖表的標(biāo)題、坐標(biāo)軸、網(wǎng)格、圖例等圖表元素。下面的例子展示了如何使用圖表上下文繪制圖表:

evcxr_figure((640, 240), |root| {root.fill(&WHITE)?;
    // 創(chuàng)建圖表上下文
    let mut chart = ChartBuilder::on(&root)
        .caption("圖表標(biāo)題", ("Arial", 20).into_font())
        .build_cartesian_2d(0f32..1f32, 0f32..1f32)?;
    // 將數(shù)據(jù)繪制到圖表上
    chart.draw_series((1..10).map(|x|{let x = x as f32/10.0;
        Circle::new((x, x), 5, &RED)
    }))?;
    Ok(())
}).style("width:60%")

上面的代碼首先用ChartBuilder::on方法創(chuàng)建圖表上下文,這里需要傳入繪圖區(qū)域,將圖表上下文綁定在此繪圖區(qū)域上。然后用caption方法設(shè)置圖表的標(biāo)題,用build_cartesian_2d方法設(shè)置直角坐標(biāo)系的取值范圍。

創(chuàng)建好圖表上下文后,我們就可以調(diào)用圖表上下文的draw_series方法繪制圖表的內(nèi)容。這里只是簡單地畫了10個散點,效果如下:

在這里插入圖片描述

上面的圖表可能不像圖表,因為沒有將坐標(biāo)軸畫出來。其實圖表中有很多元素可以設(shè)置,上面的例子只展示了標(biāo)題和內(nèi)容,下一節(jié)我們會逐個看一下圖表都有哪些組成元素以及如何配置他們。

添加圖表元素

Plotters允許我們靈活地向圖表中添加坐標(biāo)軸、網(wǎng)格、圖例等元素,本節(jié)我們就來看一下如何向圖表中添加這些元素。

添加網(wǎng)格

我們首先向上一節(jié)的圖表中加入網(wǎng)格。很簡單,只需要加入一句chart.configure_mesh().draw()?;即可:

evcxr_figure((640, 240), |root| {root.fill(&WHITE)?;
    // 創(chuàng)建圖表上下文
    let mut chart = ChartBuilder::on(&root)
        .caption("帶網(wǎng)格的圖表", ("Arial", 20).into_font())
        .build_cartesian_2d(0f32..1f32, 0f32..1f32)?;
    // 繪制網(wǎng)格
    chart.configure_mesh().draw()?;
    // 將數(shù)據(jù)繪制到圖表上
    chart.draw_series((1..10).map(|x|{let x = x as f32/10.0;
        Circle::new((x, x), 5, &RED)
    }))?;
    Ok(())
}).style("width:60%")

在這里插入圖片描述

網(wǎng)格支持很多配置可以控制網(wǎng)格的呈現(xiàn)形式。bold_line_stylelight_line_style方法可以控制主/副網(wǎng)格線的顏色和透明度,如果想隱藏網(wǎng)格線可以傳入&TRANSPARENT。x_labelsy_labels方法可以設(shè)置坐標(biāo)軸的刻度。如果想禁用某個軸上的網(wǎng)格,可以用disable_x_meshdisable_y_mesh方法。下面代碼可以實現(xiàn)隱藏x軸向網(wǎng)格,隱藏副網(wǎng)格線,y軸網(wǎng)格顯示10個刻度:

chart.configure_mesh()
	.y_labels(10)
	.light_line_style(&TRANSPARENT)
	.disable_x_mesh()

在這里插入圖片描述

關(guān)于網(wǎng)格的更多配置,請參考MeshStyle in plotters::chart - Rust (docs.rs)

添加坐標(biāo)軸

其實在我們調(diào)用build_cartesian_2d方法時,坐標(biāo)軸就已經(jīng)建立好了。那為什么我們看不到圖表中有坐標(biāo)軸呢?這是因為我們沒有設(shè)置坐標(biāo)軸的顯示區(qū)域。Plotters中用x_label_area_sizey_label_area_size來設(shè)置橫坐標(biāo)和縱坐標(biāo)的顯示區(qū)域。我們只要在創(chuàng)建圖表上下文時設(shè)置橫坐標(biāo)/縱坐標(biāo)的高度/寬度即可。

evcxr_figure((640, 240), |root| {root.fill(&WHITE)?;
    // 創(chuàng)建圖表上下文
    let mut chart = ChartBuilder::on(&root)
        .caption("帶坐標(biāo)軸和網(wǎng)格的圖表", ("Arial", 20).into_font())
    	.x_label_area_size(40) // x軸顯示區(qū)域(高度)
        .y_label_area_size(40) // y軸顯示區(qū)域(寬度)
        .build_cartesian_2d(0f32..1f32, 0f32..1f32)?;
    // 繪制網(wǎng)格
    chart.configure_mesh()
        .y_labels(10)
        .light_line_style(&TRANSPARENT)
        .disable_x_mesh()
        .draw()?;
    // 將數(shù)據(jù)繪制到圖表上
    chart.draw_series((1..10).map(|x|{let x = x as f32/10.0;
        Circle::new((x, x), 5, &RED)
    }))?;
    Ok(())
}).style("width:60%")

在這里插入圖片描述

我們還可以調(diào)用MeshStyle的x_descy_desc方法為坐標(biāo)軸設(shè)置描述:

chart.configure_mesh()
    .x_desc("X軸描述")
    .y_desc("Y軸描述")
	...

在這里插入圖片描述

添加圖例

如果圖表中有多個圖線,一般我們需要添加圖例加以區(qū)分。Plotters中可以在繪制圖線后用label方法設(shè)置圖例名稱,用legend繪制圖例。由于圖例是單獨的元素,設(shè)置好后需要調(diào)用configure_series_labels().draw()才能繪制出來,請看下面的代碼:

chart.draw_series((1..10).map(|x|{let x = x as f32/10.0;
        Circle::new((x, x), 5, &RED)
    }))?
    .label("y=x")
    .legend(|(x, y)| Circle::new((x+20, y), 4, &RED));
    
    chart.configure_series_labels().draw()?;

在這里插入圖片描述

常見圖表

與其他圖標(biāo)庫不同,Plotters并沒有內(nèi)置任何形式的圖表,而是將圖表抽象為一個叫series的概念。這樣做大的好處是靈活,可以方便地將兩種不同類型的圖組合在一起。

為了使用方便,Plotters內(nèi)置了幾個常用的series,分別是:

  • 散點圖
  • 折線圖
  • 直方圖

我們也可以定義自己的serires,然后根據(jù)數(shù)據(jù)在圖上的坐標(biāo)繪制任意圖形,靈活程度非常高。

散點圖

我們先來隨機創(chuàng)建一些點:

:dep rand = {version = "0.6.5" }
extern crate rand;

use rand::distributions::Normal;
use rand::distributions::Distribution;
use rand::thread_rng;
let sd = 0.13;
let random_points:Vec<(f64,f64)>= {let mut norm_dist = Normal::new(0.5, sd);
    let (mut x_rand, mut y_rand) = (thread_rng(), thread_rng());
    let x_iter = norm_dist.sample_iter(&mut x_rand);
    let y_iter = norm_dist.sample_iter(&mut y_rand);
    x_iter.zip(y_iter).take(1000).collect()
};

這里我們用正態(tài)分布生成了1000個點。

用Plotters繪制散點圖很簡單。只需要傳入坐標(biāo)序列即可。下面的示例顯示了如何制作2D正態(tài)分布圖。紅色矩形是 2 σ 2\sigma 2σ面積,紅色十字是平均值。

evcxr_figure((640, 480), |root| {root.fill(&WHITE)?;
    // The following code will create a chart context
    let mut chart = ChartBuilder::on(&root)
        .caption("隨機正態(tài)分布散點圖", ("Arial", 20).into_font())
        .x_label_area_size(40)
        .y_label_area_size(40)
        .build_ranged(0f64..1f64, 0f64..1f64)?;
    
    chart.configure_mesh()
        .disable_x_mesh() // 隱藏網(wǎng)格
        .disable_y_mesh() // 隱藏網(wǎng)格
        .draw()?;
    
    // 繪制散點
    chart.draw_series(random_points.iter().map(|(x,y)| Circle::new((*x,*y), 3, GREEN.filled())));
    
    // 繪制紅色矩形,框住2σ區(qū)域
    let area = chart.plotting_area();
    let two_sigma = sd * 2.0;
    area.draw(&Rectangle::new(
        [(0.5 - two_sigma, 0.5 - two_sigma), (0.5 + two_sigma, 0.5 + two_sigma)], 
        RED.mix(0.3).filled())
    )?;
    // 標(biāo)出均值位置
    area.draw(&Cross::new((0.5, 0.5), 5, &RED))?;
    
    Ok(())
}).style("width:60%")

在這里插入圖片描述

折線圖

Plotters提供了LineSeries用于繪制折線圖,只需要傳入一系列坐標(biāo)點序列,Plotters就能將這些點連成折線。下面示例展示了如何用LineSeries繪制正弦曲線和余弦曲線:

evcxr_figure((640, 480), |root| {let x_axis = (-3.4f32..3.4).step(0.01);
    root.fill(&WHITE)?;
    let mut chart = ChartBuilder::on(&root)
        .margin(5)
        .set_all_label_area_size(50)
        .caption("正弦曲線和余弦曲線", ("sans-serif", 20))
        .build_cartesian_2d(-3.4f32..3.4, -1.2f32..1.2f32)?;
    
    chart.configure_mesh()
        .x_labels(20)
        .y_labels(10)
        .disable_mesh()
        .x_label_formatter(&|v| format!("{:.1}", v))
        .y_label_formatter(&|v| format!("{:.1}", v))
        .draw()?;
    
    // 繪制正弦曲線
    chart.draw_series(LineSeries::new(x_axis.values().map(|x| (x, x.sin())), &RED))?
        .label("正弦")
        .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &RED));
    
    // 繪制余弦曲線
    chart.draw_series(LineSeries::new(
        x_axis.values().map(|x| (x, x.cos())),
        &BLUE,
    ))?
    .label("余弦")
    .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], &BLUE));

    chart.configure_series_labels().border_style(&BLACK).draw()?;
    
    Ok(())
}).style("width:60%")

在這里插入圖片描述

直方圖

在數(shù)據(jù)可視化中直方圖也是用的最多的一種圖。Plotters提供了Histogram生成直方圖series。下面的代碼分別統(tǒng)計了散點圖中隨機點在x軸和y軸上的分布:

evcxr_figure((640, 480), |root| {let areas = root.split_evenly((2,1));
    let mut charts = vec![];
    root.fill(&WHITE)?;
   for (area, name) in areas.iter().zip(["X", "Y"].into_iter()) {let mut chart = ChartBuilder::on(&area)
            .caption(format!("{}軸直方圖", name), ("Arial", 20).into_font())
            .x_label_area_size(40)
            .y_label_area_size(40)
            .build_cartesian_2d(0u32..100u32, 0f64..0.5f64)?;
        chart.configure_mesh()
            .disable_x_mesh()
            .disable_y_mesh()
            .y_labels(5)
            .x_label_formatter(&|x| format!("{:.1}", *x as f64 / 100.0))
            .y_label_formatter(&|y| format!("{}%", (*y * 100.0) as u32))
            .draw()?;
        charts.push(chart);
    }
    
    let hist_x = Histogram::vertical(&charts[0])
        .style(RED.filled())
        .margin(0)
        .data(random_points.iter().map(|(x,_)| ((x*100.0) as u32, 0.01)));
    
    let hist_y = Histogram::vertical(&charts[0])
        .style(GREEN.filled())
        .margin(0)
        .data(random_points.iter().map(|(_,y)| ((y*100.0) as u32, 0.01)));
    
    charts[0].draw_series(hist_x);
    charts[1].draw_series(hist_y);
    
    Ok(())
}).style("width:60%")

在這里插入圖片描述

多圖組合

Plotter最強大的地方就是可以通過分割子圖將多個圖表組合在一起。我們可以將隨機點的散點圖和各軸上的分布直方圖組合在一起:

evcxr_figure((640, 480), |root| {root.fill(&WHITE)?;
    let root = root.titled("散點圖組合直方圖", ("Arial", 20).into_font())?;
    let areas = root.split_by_breakpoints([560], [80]);
    let mut x_hist_ctx = ChartBuilder::on(&areas[0])
        .y_label_area_size(40)
        .build_cartesian_2d(0u32..100u32, 0f64..0.5f64)?;
    let mut y_hist_ctx = ChartBuilder::on(&areas[3])
        .x_label_area_size(40)
        .build_cartesian_2d(0f64..0.5f64, 0..100u32)?;
    let mut scatter_ctx = ChartBuilder::on(&areas[2])
        .x_label_area_size(40)
        .y_label_area_size(40)
        .build_cartesian_2d(0f64..1f64, 0f64..1f64)?;
    scatter_ctx.configure_mesh()
        .disable_x_mesh()
        .disable_y_mesh()
        .draw()?;
    scatter_ctx.draw_series(random_points.iter().map(|(x,y)| Circle::new((*x,*y), 3, BLUE.filled())))?;
    let x_hist = Histogram::vertical(&x_hist_ctx)
        .style(RED.filled())
        .margin(0)
        .data(random_points.iter().map(|(x,_)| ((x*100.0) as u32, 0.01)));
    let y_hist = Histogram::horizontal(&y_hist_ctx)
        .style(GREEN.filled())
        .margin(0)
        .data(random_points.iter().map(|(_,y)| ((y*100.0) as u32, 0.01)));
    x_hist_ctx.draw_series(x_hist)?;
    y_hist_ctx.draw_series(y_hist)?;
    
    Ok(())
}).style("width:60%")

在這里插入圖片描述

結(jié)語

盡管Plotters與Python的matplotlib思想和用法不同,但與matplotlib比Plotters有很多優(yōu)勢:

  1. 靈活,Plotters不固定圖表類型,而是通過高度抽象的模型和組件元素讓開發(fā)者可以自由創(chuàng)作任意想要的圖表
  2. 快速,得益于Rust的性能,使Plotters可以輕松處理上億數(shù)據(jù)的可視化,這在Python和JavaScript中幾乎是不可能的。
  3. 支持WebAssembly ,Plotters對wasm支持良好,通過wasm,Plotters可以運行在網(wǎng)頁上,替代JavaScript處理大量數(shù)據(jù)的可視化,提升頁面性能,優(yōu)化使用體驗。

Plotters的功能和配置項非常多,本文只選擇日常最常用的功能和圖表做了講解和演示,更多內(nèi)容請閱讀Plotters Developer’s Guide。

你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧


新聞標(biāo)題:Rust機器學(xué)習(xí)之Plotters-創(chuàng)新互聯(lián)
URL分享:http://weahome.cn/article/dhoops.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部