Obtenir des résultats de type ggplot matplotlib avec la crate Rust plotters
Le code Rust suivant est le plus proche que j’ai pu obtenir de l’exemple ggplot de matplotlib en utilisant la crate Rust plotters.
Code Rust
src/main.rs
use plotters::prelude::*;
use plotters::style::{RGBColor, ShapeStyle};
use std::error::Error;
const GGPLOT_RED: RGBColor = RGBColor(0xE2, 0x4A, 0x33);
fn main() -> Result<(), Box<dyn Error>> {
// Créer une zone de dessin et configurer le graphique
let root = BitMapBackend::new("sine_wave_plot.png", (1024, 768)).into_drawing_area();
// arrière-plan global de la figure (le garder blanc)
root.fill(&WHITE)?;
// Définir la zone du graphique (nous allons rendre le panneau de tracé gris clair pour servir d'arrière-plan de grille)
let mut chart = ChartBuilder::on(&root)
.caption("Sine Wave", ("sans-serif", 30).into_font())
.margin(24)
.x_label_area_size(50)
.y_label_area_size(50)
.build_cartesian_2d(0f64..2f64 * std::f64::consts::PI, -1.2f64..1.2f64)?;
// Remplir la zone de tracé avec un gris clair pour servir d'arrière-plan de grille
// matplotlib ggplot : axes.facecolor = E5E5E5
chart.plotting_area().fill(&RGBColor(0xE5, 0xE5, 0xE5))?;
// Configurer la grille (style de type ggplot avec des lignes de grille subtiles)
chart.configure_mesh()
.x_labels(10)
.y_labels(5)
.x_label_formatter(&|x| format!("{:.1}π", x / std::f64::consts::PI))
.y_label_formatter(&|y| format!("{:.1}", y))
.x_desc("Angle (radians)")
.y_desc("Amplitude")
// matplotlib ggplot : axes.labelcolor/xtick.color/ytick.color = 555555
.label_style(TextStyle::from(("sans-serif", 12).into_font()).color(&RGBColor(0x55, 0x55, 0x55)))
.axis_desc_style(TextStyle::from(("sans-serif", 16).into_font()).color(&RGBColor(0x55, 0x55, 0x55)))
// matplotlib ggplot : grid.color = white (grille principale) ; la grille secondaire est désactivée par défaut
.max_light_lines(0)
.bold_line_style(ShapeStyle::from(&WHITE).stroke_width(1))
.light_line_style(ShapeStyle::from(&WHITE).stroke_width(1))
// matplotlib ggplot : axes.edgecolor = white, axes.linewidth = 1
.axis_style(ShapeStyle::from(&WHITE).stroke_width(1))
// garantir des graduations vers l'extérieur (une valeur négative pointerait vers l'intérieur)
.set_all_tick_mark_size(5)
.draw()?;
// Générer les points de données de l'onde sinusoïdale
let mut sine_data = Vec::new();
for i in 0..=1000 {
let x = i as f64 * 2.0 * std::f64::consts::PI / 1000.0;
sine_data.push((x, x.sin()));
}
// Dessiner l'onde sinusoïdale
chart.draw_series(LineSeries::new(
sine_data,
ShapeStyle::from(&GGPLOT_RED).stroke_width(2),
))?
.label("sin(x)")
.legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], ShapeStyle::from(&GGPLOT_RED).stroke_width(3)));
// Dessiner la légende
chart.configure_series_labels()
.background_style(&RGBColor(0xE5, 0xE5, 0xE5).mix(0.9))
.border_style(&WHITE)
.label_font(("sans-serif", 14))
.position(SeriesLabelPosition::UpperRight)
.draw()?;
Ok(())
}Cargo.toml
[package]
name = "plottest"
version = "0.1.0"
edition = "2021"
[dependencies]
plotters = "0.3.5"
Code Python de référence
sine_wave_plot.py
#!/usr/bin/env python3
"""Générer un tracé d'onde sinusoïdale dans le style ggplot et l'enregistrer dans `sine_wave_plot_py.png`.
Utilisation :
python3 plot_sine.py
Installer les dépendances :
python3 -m pip install -r requirements.txt
"""
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter
plt.style.use("ggplot")
# Données
x = np.linspace(0, 2 * np.pi, 1000)
y = np.sin(x)
# Figure dimensionnée pour approximer 1024x768 à 100 DPI
fig, ax = plt.subplots(figsize=(10.24, 7.68))
ax.plot(x, y, color="red", alpha=0.8, linewidth=2, label="sin(x)")
# Formater les graduations x en multiples de π
def pi_label(value, _pos):
val = value / np.pi
if abs(val) < 1e-6:
return "0"
return f"{val:.1f}π"
ax.xaxis.set_major_locator(plt.MaxNLocator(10))
ax.xaxis.set_major_formatter(FuncFormatter(pi_label))
# Étiquettes, titre, légende
ax.set_xlabel("Angle (radians)", fontsize=16)
ax.set_ylabel("Amplitude", fontsize=16)
ax.set_title("Sine Wave", fontsize=24, fontweight="bold")
ax.legend(fontsize=12)
# Grille et mise en page
ax.grid(True)
plt.tight_layout()
# Enregistrer le fichier
plt.savefig("sine_wave_plot_py.png", dpi=100)
# Décommenter pour afficher de manière interactive
# plt.show()
Discussion des différences
Note : Je n’ai pas essayé de faire correspondre la taille de police, etc., de quelque manière que ce soit.
Comme vous pouvez le voir, avec un peu d’effort manuel, les deux tracés se ressemblent beaucoup. Cependant, comme l’anticrénelage n’est pas implémenté dans la crate plotters pour le moment (au 2026-01-30), le tracé Rust apparaît nettement plus « crénelé » que celui de matplotlib.
Quand on parle de tracés de qualité publication, c’est un inconvénient important et pour cette raison je ne peux pas le recommander. J’espère que l’anticrénelage sera implémenté à l’avenir.
Gros plan sur l’anticrénelage de Python

Gros plan sur l’« anticrénelage » de Rust (aucun)

Check out similar posts by category:
Rust, Python, Data Visualization
If this post helped you, please consider buying me a coffee or donating via PayPal to support research & publishing of new posts on TechOverflow