u/bongbalok

ggsketch 2.0: hand-drawn ggplot2 geoms in pure R, now with drawing media
▲ 101 r/rstats

ggsketch 2.0: hand-drawn ggplot2 geoms in pure R, now with drawing media

https://i.redd.it/2zd8qeolt8bh1.gif

I posted v1.5 of ggsketch here a while back. Short version if you missed it: the sketchy hand-drawn look as real ggplot2 geoms - pure R, no JavaScript, no browser, clean PDF/SVG export, and all the wobble is seeded so plots stay reproducible.

2.0 ended up much bigger than I intended.

The main change is that lines now have a medium: pen, ink, brush, pencil, charcoal, chalk, marker, highlighter, crayon and a few others, 13 in all. Set it as a constant or map it with aes(medium = ) like anything else. Getting there meant making strokes variable-width, which grid won't do with a polyline, so each stroke is now a filled ribbon built around a re-roughened centreline. That's what lets ink pool at the end of a stroke and a brush swell through the middle.

I also fell down two rabbit holes. geom_sketch_engrave() shades by hatch density the way old engravings build shadow - the relief map in the images is just volcano. And there's a watercolor fill now: the violins in the images are the exact example from my last post with fill_style = "watercolor" added.

Beyond that: a pile of new chart types (waterfall, gantt, calendar heatmap, treemap, chord, radar, dendrogram, and more - the geom count is at 89, which is getting silly), repelled labels with hand-drawn leader lines, and animate_sketch(), which either "boils" a plot or draws it on stroke by stroke. Both GIFs attached are a single function call.

Same caveat as last time: I build this working with AI, with me driving the design and checking the behaviour.

The example from last post, one argument later:

library(ggplot2)
library(ggsketch)

ggplot(mpg, aes(class, hwy, fill = class)) +
  geom_sketch_violin(fill_style = "watercolor", show.legend = FALSE, seed = 1) +
  scale_fill_sketch() +
  labs(title = "Highway mpg by class") +
  theme_sketch(rough_frame = TRUE)

2.0.0 is submitted to CRAN. Until it lands:

pak::pak("orijitghosh/ggsketch")

Gallery of every geom: https://orijitghosh.github.io/ggsketch/articles/gallery.html

Docs: https://orijitghosh.github.io/ggsketch/

As before, feedback is very welcome - especially if the API feels off somewhere, or there's a medium or chart type you'd want. And if you make something with it, I'd love to see it.

reddit.com
u/bongbalok — 2 days ago
▲ 105 r/rstats

ggsketch: hand-drawn ggplot2 geoms in pure R

I've used ggrough on and off for years and always liked the sketchy aesthetic, but the way it works has bothered me for a while. It redraws a finished plot as SVG in the browser, so you can't export a clean PDF, it doesn't compose with the ggplot grammar, and the package has been more or less dormant for a while now. I kept thinking these really ought to be proper geoms, and then never did anything about it, mostly because I didn't know how.

I can use ggplot2 comfortably, but writing geoms is a different skill set entirely - grobs, ggproto, grid. I tried reading through the ggplot2 internals a couple of times and didn't get far. So the idea just sat in my notes for a long time.

What finally got it built was working through it with AI as a sounding board. I won't pretend I hand-wrote every line, but I did have to understand the design decisions well enough to drive them: how to layer the package, keeping all the randomness seeded so plots stay reproducible, the fill algorithm, and supporting both ggplot2 3.5 and 4.0. It mostly closed the gap between knowing what I wanted and actually being able to implement it in grid. I'd rather be upfront about that than pretend otherwise.

It's pure R - no JavaScript, no browser. Because they're real geoms, aes(), facets, scales, and stats all work as usual, and it renders correctly to PDF and SVG.

A quick example:

library(ggplot2)
library(ggsketch)


ggplot(mpg, aes(class, hwy, fill = class)) +
  geom_sketch_violin(show.legend = FALSE, seed = 1) +
  scale_fill_sketch() +
  labs(title = "Highway mpg by class") +
  theme_sketch(rough_frame = TRUE)

The rough_frame = TRUE roughens the gridlines and axes as well, not just the data, which I think reads better. Everything is seeded, so the same seed gives the same wobble every time. The hachure fill is a scan-line filler that handles concave shapes correctly, so violins and other awkward polygons don't fall apart. There's a fairly wide set of geoms already - points, lines, bars, histograms, densities, violins, boxplots, smooths, contours, error bars, and so on.

Not on CRAN yet (working towards it). For now:

pak::pak("orijitghosh/ggsketch")

Docs and a gallery of every geom: https://orijitghosh.github.io/ggsketch/

I'd genuinely appreciate feedback, particularly if the API feels off anywhere or there's a geom you'd want that I haven't covered. And if you make something with it, I'd love to see it.

u/bongbalok — 15 days ago