feat(geom_rect): add a hatch aesthetic by floringogianu · Pull Request #1122 · has2k1/plotnine · GitHub
Skip to content

feat(geom_rect): add a hatch aesthetic - #1122

Open
floringogianu wants to merge 1 commit into
has2k1:mainfrom
floringogianu:feat/hatch
Open

floringogianu wants to merge 1 commit into
has2k1:mainfrom
floringogianu:feat/hatch

Conversation

@floringogianu

Copy link
Copy Markdown

Fixes #238

image
from plotnine import *
from plotnine.data import mpg

(
    ggplot(mpg, aes("class", fill="drv", hatch="drv"))
    + geom_bar(position="dodge", color="black")
    + scale_hatch_manual(values=["//", "xx", ".."])
    + labs(x="vehicle class", y="count", fill="drive", hatch="drive")
)

Adds a hatch aesthetic to geom_rect and everything built on it (geom_bar, geom_col, geom_histogram, geom_tile, geom_bin_2d), settable as a literal (geom_col(hatch="//")) or mapped through a discrete scale (geom_col(aes(hatch="grp"))).

A matplotlib Collection takes one hatch pattern for all of its paths, so each distinct pattern gets an overlay PolyCollection with no fill and no border, drawn over the parent. The strokes take the color aesthetic, matplotlib's convention for a hatch, and fall back to rcParams["patch.edgecolor"] when color is unset. The overlay's linewidth is zero so the parent keeps sole ownership of the border and its linetype.

geom_polygon.draw_group carries the hatch through as well, since geom_rect delegates to it under a non-linear coord.

Legend keys repeat the pattern by round(HATCH_KEY_SIZE / key_size), so a small key stays legible while a large one converges on the density the panel draws.

Scale family modelled on scale_linetype:

  • scale_hatch (discrete) / scale_hatch_discrete
  • scale_hatch_identity
  • scale_hatch_manual (custom per-level patterns)
  • scale_hatch_continuous raises PlotnineError, mirroring scale_linetype_continuous

labs(hatch=...) names the legend.

Adds a `hatch` aesthetic to geom_rect and everything built on it
(geom_bar, geom_col, geom_histogram, geom_tile, geom_bin_2d),
settable as a literal (geom_col(hatch="//")) or mapped through a
discrete scale (geom_col(aes(hatch="grp"))).

A matplotlib Collection takes one hatch pattern for all of its
paths, so each distinct pattern gets an overlay PolyCollection with
no fill and no border, drawn over the parent. The strokes take the
`color` aesthetic, matplotlib's convention for a hatch, and fall
back to rcParams["patch.edgecolor"] when color is unset. The
overlay's linewidth is zero so the parent keeps sole ownership of
the border and its linetype.

geom_polygon.draw_group carries the hatch through as well, since
geom_rect delegates to it under a non-linear coord.

Legend keys repeat the pattern by round(HATCH_KEY_SIZE / key_size),
so a small key stays legible while a large one converges on the
density the panel draws.

Scale family modeled on scale_linetype:
- scale_hatch (discrete) / scale_hatch_discrete
- scale_hatch_identity
- scale_hatch_manual (custom per-level patterns)
- scale_hatch_continuous raises PlotnineError, mirroring
  scale_linetype_continuous

`labs(hatch=...)` names the legend.
@codecov

codecov Bot commented Sep 7, 2026

Copy link
Copy Markdown

@has2k1

has2k1 commented Sep 11, 2026

Copy link
Copy Markdown
Owner

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Fill with patterns

2 participants