Getting started
Coming from ggplot2
phiz follows ggplot2’s grammar: data, aesthetic mappings, layers of geoms, scales, coordinates, facets, labels, and themes. Most ggplot2 code translates line by line. This page lists the translations, then the places where phiz behaves differently because Vega-Lite renders the plot.
Translating a plot
ggplot(mpg, aes(displ, hwy, colour = drv)) +
geom_point(alpha = 0.5) +
geom_smooth(method = "lm") +
facet_wrap(~year) +
scale_y_log10() +
labs(x = "Displacement (L)", y = "Highway mpg") +
theme_minimal()In phiz, the pipe form keeps ggplot2’s function names. The method chain builds the same plot on PHP 8.3 and 8.4.
ggplot($mpg, aes(x: 'displ', y: 'hwy', color: 'drv')) |>
geom_point(alpha: 0.5) |>
geom_smooth(method: 'lm') |>
facet_wrap('year') |>
scale_y_log10() |>
labs(x: 'Displacement (L)', y: 'Highway mpg') |>
theme_minimal();Plot::of($mpg)
->aes(x: 'displ', y: 'hwy', color: 'drv')
->point(alpha: 0.5)
->smooth(method: 'lm')
->facetWrap('year')
->scaleY(type: 'log')
->labs(x: 'Displacement (L)', y: 'Highway mpg')
->theme('minimal');Aesthetics are named arguments, so aes(displ, hwy) becomes aes(x: 'displ', y: 'hwy'). Field names are strings. colour and alpha are accepted as aliases of color and opacity.
Geoms and stats
| ggplot2 | phiz |
|---|---|
geom_point(), geom_jitter() |
point(), jitter() |
geom_line(), geom_path(), geom_step() |
line(), path(), step() |
geom_area(), geom_ribbon() |
area(), ribbon() |
geom_bar(), geom_col() |
bar(), col() |
geom_histogram(), geom_freqpoly() |
histogram(), freqpoly() |
geom_density() |
density() |
geom_boxplot() |
boxplot() |
geom_violin() |
violin() |
geom_errorbar(), geom_linerange(), geom_pointrange() |
errorbar(), linerange(), pointrange() |
geom_hline(), geom_vline(), geom_abline() |
hline(), vline(), abline() |
geom_segment() |
segment() |
geom_text(), geom_label() |
text(), label() |
geom_tile(), geom_raster(), geom_rect() |
tile(), raster(), rect() |
geom_bin2d(), geom_hex() |
bin2d(), hex() |
geom_smooth() (loess, lm, poly) |
smooth() |
geom_density_2d(), geom_density_2d_filled() |
density2d(), density2dFilled() |
geom_contour(), geom_contour_filled() |
contour(), contourFilled() |
geom_polygon() |
polygon() |
stat_summary() |
summary() |
geom_crossbar() |
crossbar() |
geom_count() |
count() |
stat_ellipse() |
ellipse() |
annotate() |
annotate() |
geom_function(), stat_function() |
curve() |
geom_rug() |
rug() |
stat_ecdf() |
ecdf() |
stat_qq(), stat_qq_line() |
qq(), qqLine() |
coord_polar() with bars |
coordPolar(), or arc() and pie() |
Geom arguments keep ggplot2’s names where they exist: bins, binwidth, boundary, breaks, position, method, se, level, span, adjust, h, n, coef, outliers, width, hjust, vjust, angle, nudge_x (as nudgeX), fun.data (as funData), contour_var (as contourVar), and inherit.aes (as inheritAes). position takes the strings 'stack', 'dodge', 'fill', and 'identity'.
Scales, coordinates, facets, and themes
| ggplot2 | phiz |
|---|---|
scale_x_continuous(name, breaks, labels, limits) |
scaleX(name:, breaks:, format:, domain:) |
scale_x_log10(), scale_x_sqrt(), scale_x_reverse() |
scaleX(type: 'log'), scaleX(type: 'sqrt'), scaleX(reverse: true) |
scale_x_date(date_labels = "%Y") |
scaleX(type: 'time', format: '%Y') |
scale_colour_manual(values = c(a = "red")) |
scaleColor(values: ['a' => 'red']) |
scale_colour_brewer(palette = "Set2") |
scaleColor(scheme: 'set2') |
scale_colour_distiller(), scale_colour_fermenter() |
the functions of the same names |
scale_colour_viridis_c(option = "A") |
scale_color_viridis_c(option: 'A') |
scale_colour_gradient2(midpoint = 0), scale_colour_gradientn() |
the functions of the same names |
scale_colour_grey(), scale_colour_hue(l = 45), scale_colour_identity() |
the functions of the same names |
scale_x_discrete(limits, labels) |
scale_x_discrete(limits:, labels:) |
scale_y_continuous(labels = scales::label_percent()) |
scaleY(labels: label_percent()) |
label_comma(), label_dollar(), label_number(), label_scientific(), label_date() |
the functions of the same names |
guides(colour = "none", x = guide_axis(angle = 45)) |
guides(color: 'none', x: guide_axis(angle: 45)) |
guide_axis(cap = "both") |
guide_axis(cap: true) |
coord_flip() |
coordFlip() |
coord_cartesian(xlim, ylim) |
coordCartesian(xlim:, ylim:) |
coord_fixed(ratio), coord_equal() |
coordFixed(ratio) |
coord_polar(theta = "y") |
coordPolar(theta: 'y') |
facet_wrap(~f, ncol, scales) |
facetWrap('f', ncol:, scales:) |
facet_grid(r ~ c, labeller = label_both) |
facetGrid(rows: 'r', cols: 'c', labeller: 'both') |
labeller = as_labeller(c(f = "Front")) |
labeller: ['f' => 'Front'] |
labs(), ggtitle(), xlab(), ylab() |
labs(), title(), and the functions of the same names |
theme_gray(), theme_bw(), theme_linedraw(), theme_minimal(), theme_classic(), theme_light(), theme_dark(), theme_void() |
theme('gray'), and so on |
theme(legend.position = "bottom") |
theme(legendPosition: 'bottom') |
theme(axis.text.x = element_text(angle = 45)) |
theme(xLabelAngle: 45) |
theme(legend.title = element_blank()) |
theme(legendTitle: false) |
labs(caption = "Source"), theme(plot.caption = element_text(colour, size, hjust)) |
labs(caption: 'Source'), theme(captionColor:, captionSize:, captionAnchor:) |
patchwork p1 + p2, p1 / p2 |
Compose::beside($p1, $p2), Compose::stack($p1, $p2) |
factor(cyl) |
factor('cyl') or 'cyl:N' |
after_stat(density) in a histogram |
histogram(density: true) |
Differences
These differences follow from Vega-Lite rendering the plot.
- Sizes. Point
sizeis an area in square pixels, as in Vega-Lite, rather than a diameter in millimeters. The default is 30.linewidthis in pixels. - Bins.
bins:is a maximum, and Vega-Lite rounds the boundaries. Usebinwidth:andboundary:for exact bins. - Limits.
xlim()andylim()zoom without removing data. ggplot2 removes the data outside the limits, which changes statistics computed from it. - Densities. The default bandwidth is Vega-Lite’s.
adjust:multiplies R’sbw.nrd0, soadjust: 1reproduces ggplot2’s default. - Smoothers. Loess,
lm,quad, andpolyfits and their confidence bands are computed in PHP and match R. Loess matchesloess(surface = "direct"); ggplot2 interpolates the loess surface, which moves the curve slightly. Above 3,000 rows, loess falls back to Vega-Lite’s transform without a band, where ggplot2 switches to a GAM. There is nogammethod. - Colors. Categorical colors come from Vega-Lite’s palette by default.
theme('gray')switches to ggplot2’shue_pal()colors, computed for the number of levels.scaleColor(values:)orscheme:sets them explicitly. - Panels. A discrete axis is 300 pixels by default, the same as a continuous axis, and grows by 20 pixels per level beyond 15 levels.
- Violins.
violin()draws each violin as a Vega-Lite trail, whose ends are rounded. There is nodraw_quantilesoption; layer aboxplot()instead. - Polar coordinates.
coordPolar()draws bars, columns, and arcs. Vega-Lite has no polar form for lines, points, or areas, so radar charts are not available. - Not available. There is no
sec_axis(), nogeom_dotplot(), and nogeom_quantile(). Useraw()orlayer()for any Vega-Lite feature phiz does not wrap.
Additions
phiz adds features that ggplot2 leaves to other packages:
- tooltips, pan and zoom, brushing, legend highlighting, and sliders (see Interaction)
- linked views across compositions
- the statistics helpers for phit fits and CmdStanPHP draws (see Statistics)
- Vega-Lite aggregates and time units in field shorthand, such as
'mean(hwy)'and'year(date):O'
From phpstats/phiz@bc7ed3e.