---
title: "reaborn vs. seaborn vs. ggplot2"
description: >
  Where reaborn fits — a faithful seaborn API and statistics, delivered as
  extensible ggplot objects.
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{reaborn vs. seaborn vs. ggplot2}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE)
```

## Where reaborn fits

reaborn is a faithful R port of Python's **seaborn**, built on **ggplot2**. It
mirrors seaborn's public API exactly — same function names, same argument names,
same defaults — so the plotting code you already know runs in R with little to no
translation. The defaults that make seaborn plots look good out of the box (the
styles, the palettes, the spacing) come along for the ride, because reaborn
reproduces them rather than approximating them.

<img src="../reference/figures/compare-kde.png" alt="reaborn vs seaborn KDE" style="width:100%;max-width:880px;border-radius:.6rem;box-shadow:0 4px 18px rgba(0,0,0,.1)">

The part seaborn can't match: **every reaborn plot *is* a ggplot object.** A call
like `scatterplot(...)` returns a `ggplot`, so you can keep building with the full
grammar of graphics — add `facet_wrap()`, swap in `scale_x_log10()`, layer extra
geoms, override the theme. You get seaborn's defaults as a starting point and
ggplot2's composability as the ceiling.

## Coming from seaborn?

In most cases you change **nothing but the language host**. After
`library(reaborn)`, the `sns.` aliases, the global theme, and the
`True`/`False`/`None` literals are all in scope, so a seaborn snippet pasted into
R runs as-is.

```{r}
library(reaborn)   # sets seaborn theme + palette globally, like sns.set_theme()

# This is literally seaborn code — it runs verbatim in R:
sns.scatterplot(data = penguins, x = "bill_length_mm", y = "bill_depth_mm",
                hue = "species")
```

| Python (seaborn) | R (reaborn) | Note |
|---|---|---|
| `import seaborn as sns` | `library(reaborn)` | Sets theme/palette globally, exposes `sns.` aliases |
| `sns.set_theme()` | *automatic on load* | |
| `sns.scatterplot(data=df, x="a", y="b", hue="g")` | same line, verbatim | `sns.` alias + `=` kwargs both work |
| `True` / `False` / `None` | `True` / `False` / `None` | Bound to `TRUE` / `FALSE` / `NULL` |
| string columns: `x="col"` | `x = "col"` | seaborn's string-column API is preserved |
| `ax.set(...)` (matplotlib) | `+ ggplot2::labs(...)`, `+ theme(...)` | You now get the *ggplot* grammar |

## Coming from ggplot2?

You already love the grammar of graphics. reaborn doesn't ask you to give it up —
it hands you **seaborn's defaults and statistics as a starting layer, returned as
an ordinary `ggplot`** that you keep building.

- **Skip the boilerplate.** `histplot(data, x="x", hue="g")` gets you seaborn's
  binning, palette, and theme in one call — then `+ facet_wrap(~year) + scale_x_log10()`
  is yours.
- **It composes, it doesn't replace.** Everything is a real `ggplot`, so
  `patchwork`, custom scales, extra geoms, and your theme tweaks all keep working.
