Erreichen von matplotlib ggplot-ähnlichen Ergebnissen mit dem Rust plotters-Crate
Der folgende Rust-Code ist das Nähest, was ich dem matplotlib-ggplot-Beispiel mit dem Rust-plotters-Crate erreichen konnte.
Rust-Code
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>> {
// Erstelle einen Zeichenbereich und richte das Diagramm ein
let root = BitMapBackend::new("sine_wave_plot.png", (1024, 768)).into_drawing_area();
// allgemeiner Abbildungshintergrund (weiß lassen)
root.fill(&WHITE)?;
// Definiere den Diagrammbereich (wir machen das Plot-Panel hellgrau, um es als Gitterhintergrund zu nutzen)
let mut chart = ChartBuilder::on(&root)
.caption("Sinuswelle", ("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)?;
// Fülle den Plotbereich mit Hellgrau als Gitterhintergrund
// matplotlib ggplot: axes.facecolor = E5E5E5
chart.plotting_area().fill(&RGBColor(0xE5, 0xE5, 0xE5))?;
// Konfiguriere das Gitter (ggplot-ähnlicher Stil mit dezenten Gitterlinien)
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("Winkel (Bogenmaß)")
.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 (Hauptgitter); Nebengitter ist standardmäßig deaktiviert
.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))
// stelle äußere Tickmarkierungen sicher (negative würde nach innen zeigen)
.set_all_tick_mark_size(5)
.draw()?;
// Generiere Sinuswellen-Datenpunkte
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()));
}
// Zeichne die Sinuswelle
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)));
// Zeichne die Legende
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"
Referenz-Python-Code
sine_wave_plot.py
#!/usr/bin/env python3
"""Generiere einen Sinuswellen-Plot im ggplot-Stil und speichere in `sine_wave_plot_py.png`.
Verwendung:
python3 plot_sine.py
Abhängigkeiten installieren:
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")
# Daten
x = np.linspace(0, 2 * np.pi, 1000)
y = np.sin(x)
# Abbildungsgröße approximiert 1024x768 bei 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)")
# Formatiere x-Ticks in Vielfachen von π
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))
# Beschriftungen, Titel, Legende
ax.set_xlabel("Winkel (Bogenmaß)", fontsize=16)
ax.set_ylabel("Amplitude", fontsize=16)
ax.set_title("Sinuswelle", fontsize=24, fontweight="bold")
ax.legend(fontsize=12)
# Gitter und Layout
ax.grid(True)
plt.tight_layout()
# Datei speichern
plt.savefig("sine_wave_plot_py.png", dpi=100)
# Einkommentieren, um interaktiv anzuzeigen
# plt.show()
Diskussion der Unterschiede
Hinweis: Ich habe nicht versucht, die Schriftgröße etc. in irgendeiner Weise anzupassen.
Wie du sehen kannst, sehen die beiden Plots mit etwas manuellem Aufwand recht ähnlich aus. Jedoch, da Antialiasing noch nicht implementiert ist im plotters-Crate (Stand 2026-01-30), sieht der Rust-Plot deutlich “gezackter” aus als der matplotlib-Plot.
Wenn man über Publikationsqualitäts-Plots spricht, ist dies ein erheblicher Nachteil und aus diesem Grund kann ich es nicht empfehlen. Hoffentlich wird Antialiasing in Zukunft implementiert.
Nahaufnahme des Python-Antialiasing

Nahaufnahme des Rust-“Antialiasing” (keines)

Ähnliche Beiträge nach Kategorie:
Rust, Python, Data Visualization
Wenn dieser Beitrag dir geholfen hat, erwäge, mir einen Kaffee zu spendieren oder per PayPal zu spenden, um die Recherche und Veröffentlichung neuer Beiträge auf TechOverflow zu unterstützen