vplot(mtcars) |>
mark_point(x = wt, y = mpg, color = hp, size = 3)
A vellumplot plot is a stack of marks. Each mark_*() appends one drawing layer to the spec, and every mark reads the same grammar: bare column names (or expressions) captured with tidy evaluation become encodings, while scalar values become constant aesthetics. color = hp maps the hp column through a scale; color = "red" paints every element red.
vplot(mtcars) |>
mark_point(x = wt, y = mpg, color = hp, size = 3)
You can stack as many marks as you like on a panel, and scales train across all of them at once.
mark_point() draws markers; mark_line() and mark_step() connect points in x order; mark_rule() draws reference lines. mark_point() also takes shape (one of "circle", "square", "triangle", "diamond", "plus", "cross") and a position = "jitter" adjustment.
vplot(pressure) |>
mark_line(x = temperature, y = pressure) |>
mark_point(x = temperature, y = pressure)
mark_bar() draws bars from a zero baseline. Give it an explicit y for heights, or omit y and it counts rows per category (the count stat). When fill is mapped, groups stack by default; switch to side-by-side with position = "dodge" or normalise to 1 with position = "fill".
mark_area() fills between a y line and zero, mark_ribbon() fills between ymin and ymax, and the interval marks draw ranges: mark_errorbar() (with caps), mark_linerange() (without), and mark_segment() from (x, y) to (xend, yend).
vplot(pressure) |>
mark_area(x = temperature, y = pressure, fill = "steelblue", alpha = 0.4) |>
mark_line(x = temperature, y = pressure)
mark_boxplot() summarises the raw y values per x category into a box-and-whisker (box from Q1 to Q3, median line, whiskers at 1.5 times the IQR, outliers as points).
vplot(mtcars) |>
mark_boxplot(x = factor(cyl), y = mpg)
mark_tile() draws a rectangle at each (x, y) coloured by fill; mark_raster() is the same thing drawn as a single raster image (a fast path that needs a complete regular grid). For continuous data, mark_bin2d() and mark_hex() bin x and y into a grid and colour each cell by count.
grid <- expand.grid(x = 1:8, y = 1:8)
grid$z <- with(grid, sin(x / 2) + cos(y / 2))
vplot(grid) |>
mark_tile(x = x, y = y, fill = z) |>
scale_fill_continuous(palette = "Batlow")
mark_contour() draws iso-density contour lines of a 2-D point cloud (and mark_contour_filled() fills the bands), coloured by level. See the statistical marks article for the details.
vplot(faithful) |>
mark_point(x = eruptions, y = waiting, color = "grey70") |>
mark_contour(x = eruptions, y = waiting)
mark_text() draws the label aesthetic as text at each (x, y); mark_label() adds a filled background behind each label so it stays legible over busy marks. size is in points, and angle can be mapped or constant.
top <- mtcars[mtcars$mpg > 30, ]
vplot(top) |>
mark_point(x = wt, y = mpg) |>
mark_text(x = wt, y = mpg, label = rownames(top), vjust = "bottom", size = 9)
mark_pie() and mark_donut() are the part-of-whole shortcuts. Each value becomes a wedge; fill colours the slices. Under the hood they are a stacked bar projected through coord_polar(), which they set for you.
parts <- data.frame(part = c("a", "b", "c", "d"), n = c(3, 5, 2, 4))
vplot(parts) |>
mark_donut(value = n, fill = part, hole = 0.6)
Because scales train across every layer, mixing marks on one panel works. Here a point cloud and a fitted line share the same trained x and y axes.
vplot(mtcars) |>
mark_point(x = wt, y = mpg, color = factor(cyl)) |>
mark_smooth(x = wt, y = mpg, method = "lm")
From here:
mark_sf() maps and vgraph() node-link diagrams.