scale() is now set_scale() (#36).
glyph’s scale() had the same name as
base::scale(), so library(glyph) masked the
base function. It printed “The following object is masked from
‘package:base’: scale”, and base uses such as scale(df$x)
failed afterwards with an error about glyph specs.
set_scale() takes the same arguments. To update your code,
change each scale() step in a glyph pipeline to
set_scale():
# Before
glyph(mtcars, x = wt, y = mpg) |> mark_point() |> scale("y", zero = TRUE)
# After
glyph(mtcars, x = wt, y = mpg) |> mark_point() |> set_scale("y", zero = TRUE)Base uses of scale() work again and need no change.
scale_color(), scale_log() and
scale_time() keep their names. library(glyph)
no longer masks any function.
The compiled JSON (compile()$json and
export(..., "plot.json")) has a new data layout, marked by
"$schema": "glyph/v0.2" (#8). Data is
{"columns": {...}, "n": rows}, and a mark that draws the
plot’s data has
{"from": "plot", "fields": [...], "rows": [...]}, where
rows is null or lists the 0-based rows it
keeps after dropping missing values. Boxplot, violin, histogram and
polygon marks send {"values": [...]}, one record per box,
violin, bin or shape. Code that reads JSON written by glyph 0.1 needs
updating.
compile(engine = ...) accepts only
"auto" and "html", and gives an error for
anything else. It used to accept "canvas" and
"webgl" and pick one by data size, but no such renderer has
ever existed, so the choice did nothing. The D3 and SVG renderer is the
only one.
Printing a compose() layout at the console now draws
it, as printing a single plot does (#13). The text description it used
to print comes from the new
summary.glyph_layout().
glyphOutput() and
renderGlyph() place and draw a plot, and
renderGlyph() takes a plot, a compose() layout
or a widget from render(). What the user selects reaches
the server as input$<outputId>_selected: the row
numbers of the data frame given to glyph(), so
data[input$plot_selected, ] gives the selected rows. The
numbers stay right when rows with missing values are dropped and when a
mapping is computed, and selecting a box, bin or polygon selects the
rows it summarises. The value is sent when a brush ends, on a click
select and on a legend click, and clearing a selection sends
NULL. A facet() grid gives one vector, and a
compose() layout gives a list with one entry per panel,
named after the panels when compose() is given names. shiny
is suggested, not required. A new article, “Using glyph in Shiny”
(vignette("shiny", package = "glyph")), is built around an
example app in inst/examples/shiny-brush.mark_boxplot(),
mark_violin(), mark_sina() and
mark_histogram(). Their statistics are computed in R when
the plot is compiled, with stats::quantile(),
stats::density() and hist()-style bins, after
computed mappings are evaluated and rows with missing values are
dropped. They work with facet() (summaries are computed per
panel), compose(), theme tokens, tooltips (which show the
statistics), hover, click and brushing. Each box, violin or bin knows
which rows it summarises, so brushing points or linked panels highlights
the boxes and bins that contain the selected rows, and brushing a box
selects its rows.mark_polygon() draws closed shapes from x/y
vertices, one per value of group (#7). Vertices are joined
in row order, color fills each shape, style
sets the fill, outline colour, outline width and opacity, and
radius rounds the corners. Each polygon is one element: it
gets one tooltip, and brushing or clicking it selects all of its rows,
including in linked panels. It works with facet(),
compose(), zoom, theme tokens, computed mappings and NA
dropping.render() (#13).
glyph registers knit_print() methods for
glyph_spec and glyph_layout; knitr stays a
suggested package. render() is still there for setting the
width and height.compile() takes 0.1s instead of 65s, the widget is ready
for the Viewer in 0.4s, and the file is 5 MB instead of 14 MB. Plots
look and behave as before.compose(linked_selections = TRUE). Pressing Escape clears
brush selections too, unless you are typing in a text field. Plots with
a brush but no zoom now get a controls bar for the button. When the
controls don’t fit the plot’s width, as in small facet panels, they show
just their symbols, with the full label in their tooltip.vignette("custom-marks")), walks through adding a mark
type end to end with a worked example (#9). It covers the R function and
add_mark(), how mappings are resolved when the plot is
compiled, how data reaches the browser, the drawing code in
glyph.js, axes, tooltips, hover, brushing, fitting the
container, tests, and marks that summarise data. It also says plainly
that adding a mark means editing glyph’s source, and what would need to
change for other packages to add marks.ARCHITECTURE.md and the Getting Started vignette in plainer
language (#4). Removed the comparisons with ggplot2 from the
documentation, including the comparison tables in the README and the
“glyph vs ggplot2” vignette. The package Title and Description now
describe what glyph does (#5). The README and the glyph-package help
page have an “Acknowledgements” section crediting the prior art glyph’s
design draws on.R CMD check
on Windows, macOS and Linux for every pull request (#31).set_scale() is used as
given, including on the shared axes of facet() and
compose(). Point and line marks are unchanged.facet() grids,
which also overflowed narrow containers, and plots in R Markdown
documents ran past their 400px box into the text below. Plots and facet
grids are now drawn at the size of the container they are in, and are
redrawn when it is resized.compose() with named arguments, such as
compose(a = p1, b = p2), now draws (#34). The panels were
sent as an object keyed by name instead of a list, and the widget showed
a render error.export() to .html no longer fails on
machines without pandoc (#3). Instead of a low-level pandoc error, it
now writes the HTML with its JavaScript in a
<name>_files folder alongside, and says so, including
how to get a single self-contained file (install pandoc, or run inside
RStudio). The pandoc requirement is now documented in
?export.interact(zoom = TRUE)
now zooms plots that have no point mark.factor(cyl)) instead of its internal column name, and
tooltip templates can refer to fields whose names contain dots, such as
{.median} (#6).x = log(wt) or
color = factor(cyl), are now evaluated when the plot is
compiled. They used to be dropped without a message. The expression is
used as the default axis or legend label.x, y, x2, y2,
y_min, y_max) are now dropped from that mark
when the plot is compiled, with a warning that says how many rows were
removed and for which aesthetics.facet(rows =, cols =) now accepts a computed
expression, such as facet(cols = factor(cyl)), evaluated
the same way as an aesthetic mapping. The expression text used to be
taken as a column name that didn’t exist, so faceting on anything but a
plain column gave a single, unlabelled panel.facet() with a
computed mapping or with missing values behaves the same as an unfaceted
plot.?glyph no
longer claims that lists, URLs or Arrow tables are accepted as data,
?facet no longer says panels get independent scales by
default, and ?marks and ?interactivity drop
features that don’t exist. The description, documentation, README and
ARCHITECTURE.md no longer claim WebGL or canvas rendering
or standalone SVG export. A canvas renderer is planned (#20).?mark_text now describes what
smart_repel = TRUE does: it nudges overlapping label boxes
apart, pair by pair, over several passes. It credits ggrepel as the
inspiration.summary.glyph_spec and
print.glyph_layout help topics were left out because they
had no title. They are back.Authors@R and
inst/COPYRIGHTS as the author of the bundled D3.js library
(ISC license), as CRAN policy asks for bundled JavaScript.aes() required).mark_point(),
mark_line(), mark_bar(),
mark_area(), mark_text(),
mark_rule(), mark_ribbon(),
mark_link().interact(): tooltips,
zoom, brush selection, hover effects, cross-filtering, and named
selections.animate(): entrance
transitions and keyframe animation through data states.scale() with convenience
wrappers scale_color(), scale_log(),
scale_time().theme_tokens() with five
built-in presets: light, dark, minimal, publication, presentation.compose(),
marginals(), inset(), and
facet().compile(), rendering to
interactive HTML widgets via D3.js.export() and Vega-Lite
interoperability via to_vegalite().