Lograr resultados similares a ggplot de matplotlib usando el crate plotters de Rust
El siguiente código en Rust es lo más cerca que pude llegar al ejemplo de ggplot de matplotlib usando el crate plotters de Rust.
Código en 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>> {
// Crear un área de dibujo y configurar el gráfico
let root = BitMapBackend::new("sine_wave_plot.png", (1024, 768)).into_drawing_area();
// fondo general de la figura (mantenerlo blanco)
root.fill(&WHITE)?;
// Definir el área del gráfico (haremos el panel de graficación gris claro para que sea el fondo de la cuadrícula)
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)?;
// Rellenar el área de graficación con un gris claro para que sea el fondo de la cuadrícula
// matplotlib ggplot: axes.facecolor = E5E5E5
chart.plotting_area().fill(&RGBColor(0xE5, 0xE5, 0xE5))?;
// Configurar la malla (estilo similar a ggplot con líneas de cuadrícula sutiles)
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 (cuadrícula mayor); la cuadrícula menor está desactivada por defecto
.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))
// asegurar marcas hacia afuera (negativo apuntaría hacia adentro)
.set_all_tick_mark_size(5)
.draw()?;
// Generar puntos de datos de la onda senoidal
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()));
}
// Dibujar la onda senoidal
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)));
// Dibujar la leyenda
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"
Código Python de referencia
sine_wave_plot.py
#!/usr/bin/env python3
"""Genera un gráfico de onda senoidal en estilo ggplot y lo guarda en `sine_wave_plot_py.png`.
Uso:
python3 plot_sine.py
Instalar dependencias:
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")
# Datos
x = np.linspace(0, 2 * np.pi, 1000)
y = np.sin(x)
# Tamaño de figura para aproximar 1024x768 a 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)")
# Formatear marcas de x en múltiplos 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))
# Etiquetas, título, leyenda
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)
# Cuadrícula y diseño
ax.grid(True)
plt.tight_layout()
# Guardar archivo
plt.savefig("sine_wave_plot_py.png", dpi=100)
# Descomentar para mostrar de forma interactiva
# plt.show()
Discusión de las diferencias
Nota: No intenté igualar el tamaño de fuente, etc., de ninguna manera.
Como puedes ver, con algo de esfuerzo manual, los dos gráficos se ven bastante similares. Sin embargo, como el antialiasing no está implementado en el crate plotters todavía (a fecha de 2026-01-30), el gráfico de Rust se ve significativamente más “dentado” que el de matplotlib.
Cuando se habla de gráficos de calidad para publicación, esto es una desventaja significativa y por esta razón no puedo recomendarlo. Con suerte, el antialiasing se implementará en el futuro.
Acercamiento al antialiasing de Python

Acercamiento al “antialiasing” de Rust (ninguno)

Echa un vistazo a artículos similares por categoría:
Rust, Python, Data Visualization
Si este artículo te ha ayudado, considera invitarme a un café o hacer una donación vía PayPal para apoyar la investigación y publicación de nuevos artículos en TechOverflow