diff --git a/DESCRIPTION b/DESCRIPTION index 398dd9f5..d8070459 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -20,8 +20,7 @@ Suggests: MASS, mgcv, testthat (>= 0.8.1), - knitr (>= 1.6), - rmarkdown + knitr (>= 1.6) VignetteBuilder: knitr Roxygen: list(wrap = FALSE) License: GPL-2 diff --git a/vignettes/.gitignore b/vignettes/.gitignore deleted file mode 100644 index 0361156d..00000000 --- a/vignettes/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.html -*.md \ No newline at end of file diff --git a/vignettes/axes-legends.Rmd b/vignettes/axes-legends.Rmd deleted file mode 100644 index ebba1ab5..00000000 --- a/vignettes/axes-legends.Rmd +++ /dev/null @@ -1,176 +0,0 @@ ---- -title: "Guides: Axes and Legends" -output: - html_document: - toc: true ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 3.5, fig.height = 2.5, dpi = 100) -``` - -When polishing graphics for production you often spend a lot of time getting the -axes and legends looking exactly right. This vignette describes the ggvis -functions that allow you to control plot guides: axes and legends. - -In ggvis, axes and legends are related to scales, but are described separately. -This is different to ggplot2, where the scale objects controlled both the -details of the mapping and how it should be displayed on the plot. This makes -ggvis a little more verbose, but it also makes it more flexible. - -Currently, ggvis guides are a close map to their vega equivalents. For -reference, you may also want to read the vega documentation for the -underlying [axis](https://github.com/trifacta/vega/wiki/Axes) and -[legend](https://github.com/trifacta/vega/wiki/Legends) components. - -## Common properties - -Axes and legends have relatively few components in common, but the ones that -they share are particularly important. - -* `scale` (axis), and stroke/fill/size/shape (legend) describe which scale (or - scales in the case of a legend) will be displayed on the guide - - ```{r, eval = FALSE} - add_axis(vis, "x") - add_axis(vis, "y") - add_legend(vis, "stroke") - add_legend(vis, "size") - # Display multiple scales in one legend: - add_legend(vis, "stroke", "size") - ``` - -* `title`, a string describing the guide - - ```{r, eval = FALSE} - add_axis(vis, "x", title = "My x variable") - add_legend(vis, "fill", title = "Some interesting colours") - ``` - -* `values`, used to override the default placement of ticks on an axis or gradient - legend, or visible legend labels. - -* `format`, a d3 [formatting specification](https://github.com/mbostock/d3/wiki/Formatting) - that controls how values are converted to strings. - -### Custom styles - -Finally, both axes and legends share `properties`, which is a named list of -`props()` that is applied to specified components of the axis or legend. For -axes, you can set the properties of the ticks (or majorTicks and minorTicks -separately), the labels and axis. For legends, you can set properties of the -title, label, symbols (for categorical scales), gradient (for continuous -scales), and legend. - -Currently, if you're using multiple scales, you'll need to adjust properties to make -sure that your legends don't overlap. - -```{r, results = 'asis'} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", properties = axis_props( - axis = list(stroke = "red", strokeWidth = 5), - grid = list(stroke = "blue"), - ticks = list(stroke = "blue", strokeWidth = 2), - labels = list(angle = 45, align = "left", fontSize = 20) - )) -``` - -## Axis - -```{r, results = 'asis'} -mtcars %>% ggvis(~wt, ~mpg) %>% layer_points() - -mtcars %>% ggvis(~wt, ~mpg) %>% layer_points() %>% - add_axis("x", title = "Weight") %>% - add_axis("y", title = "Miles per gallon") - -# Use title offset to push the titles further away -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", title = "Weight", title_offset = 50) %>% - add_axis("y", title = "Miles per gallon", title_offset = 50) -``` - -### Tick sizes and padding - -There are five options that control the appearance of ticks: - -* `subdivide`: the number of minor ticks between each major tick. - -* `tick_padding`: the padding between ticks and labels (in pixels) - -* `tick_size_major`, `tick_size_minor` ,`tick_size_end`: the size of the - major, minor and end ticks. By default they are all the same size as the major - ticks, but you can set them separately. - -```{r, results = 'asis'} -# Change ticks and subdivide with minor ticks -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", subdivide = 9, values = 1:6) %>% - add_axis("y", subdivide = 1, values = seq(10, 34, by = 2)) - -# Make the minor ticks smaller and the end ticks longer -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", subdivide = 9, values = 1:6, tick_size_major = 10, - tick_size_minor = 5, tick_size_end = 15, tick_padding = 20) -``` - -### Orientation - -You can control the placement of the axes with the `orient` argument: - -```{r, results = 'asis'} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", orient = "top") %>% - add_axis("y", orient = "right") -``` - -If you want axes on both sides, just add two axes: - -```{r, results = 'asis'} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x", orient = "bottom") %>% - add_axis("x", orient = "top") -``` - -You can even put multiple scales on one side: - -```{r, results = 'asis'} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_axis("x") %>% - add_axis("x", offset = 40, grid = FALSE) -``` - -This is probably more useful if you have multiple x or y position scales, but -I've already discussed that enough times in these vignettes given how much I -dislike them. - - -## Legends - -### Combining legends - -Unlike ggplot2, by default, ggvis will not combine scales based on the same -underlying variables into a single legend. Instead you must do this yourself -by supplying the name of multiple scales to one legend: - -```{r, results = 'asis'} -mtcars2 <- mtcars %>% dplyr::mutate(cyl = ordered(mtcars$cyl)) -mtcars2 %>% ggvis(~mpg, ~wt, size = ~cyl, fill = ~cyl) %>% layer_points() -mtcars2 %>% ggvis(~mpg, ~wt, size = ~cyl, fill = ~cyl) %>% layer_points() %>% - add_legend(c("size", "fill")) -``` diff --git a/vignettes/cookbook.Rmd b/vignettes/cookbook.Rmd deleted file mode 100644 index 6d9c20a1..00000000 --- a/vignettes/cookbook.Rmd +++ /dev/null @@ -1,169 +0,0 @@ ---- -title: "ggvis cookbook" -output: - html_document: - toc: true ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 2, fig.height = 1.25, dpi = 100) -``` - -The following examples show you how to create a selection of common graphics with ggvis. First, load ggvis and dplyr: - -```{r, message = FALSE} -library(ggvis) -library(dplyr) -``` - -## Scatterplots - -We'll use the built-in `mtcars` data set, and look at two columns of interest, `mpg`, and `wt`: - -```{r} -# The first few rows of mtcars -head(mtcars) -mtcars %>% ggvis(~wt, ~mpg) %>% layer_points() -``` - -Smaller points, a different shape, a different outline (stroke) color, and empty fill: - -```{r} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points(size := 25, shape := "diamond", stroke := "red", fill := NA) -``` - - -## Regression lines - -Adding a smooth line - -```{r, message = FALSE} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points() %>% - layer_smooths() -``` - -With a linear model, and 95% confidence interval for the model: - -```{r, message = FALSE} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points() %>% - layer_model_predictions(model = "lm", se = TRUE) -``` - - -## Scatter plots with grouping - -Coloring points by a variable: - -```{r, message = FALSE} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points(fill = ~factor(cyl)) -``` - -Coloring points, and adding a smoother for each group. The grouping variable (which is applied before the `transform_smooth` is calculated) must be specified with `group_by()`: - -```{r, message = FALSE} -mtcars %>% - ggvis(~wt, ~mpg, fill = ~factor(cyl)) %>% - layer_points() %>% - group_by(cyl) %>% - layer_model_predictions(model = "lm") -``` - -## Bar graphs - -We'll use the built-in `pressure` data set for these examples: - -```{r} -# The first few rows -head(pressure) -``` - -When the variable on the x axis is continuous (e.g., numeric or date-time): - -```{r, message = FALSE, fig.width = 4} -pressure %>% - ggvis(~temperature, ~pressure) %>% - layer_bars() -``` - -It's possible to specify the width of the bars: - -```{r, message = FALSE, fig.width = 4} -pressure %>% - ggvis(~temperature, ~pressure) %>% - layer_bars(width = 10) -``` - -When the variable on the x axis is categorical (e.g., factor or character): - -```{r, message = FALSE, fig.width = 4} -# First, modify the pressure data set so that the x variable is a factor -pressure2 <- pressure %>% mutate(temperature = factor(temperature)) - -pressure2 %>% ggvis(~temperature, ~pressure) %>% - layer_bars() -``` - -Notice that in this example, the x values aren't sorted quite right: they're sorted lexically, by the first, second, and then third digit, instead of by the numeric value. This is due to a limitation in ggvis. - -It's possible to work around this by using a data set with a numerical x, and then tell it to display using a nominal scale. Notice in the example below, the x-axis labels are centered under each bar, each bar has a label, and they are sorted numerically. - - -```{r, message = FALSE, fig.width = 4} -# Use the original pressure data set with continuous x values -pressure %>% ggvis(~temperature, ~pressure) %>% - layer_bars() -``` - - -## Line graphs - -```{r, message = FALSE} -pressure %>% ggvis(~temperature, ~pressure) %>% layer_lines() -``` - -Lines with points: - -```{r, message = FALSE} -pressure %>% ggvis(~temperature, ~pressure) %>% - layer_points() %>% - layer_lines() -``` - -## Histograms - -We'll use the built-in `faithful` data set for these examples: - -```{r} -# The first few rows -head(faithful) -``` - -Basic histogram: - -```{r, message = FALSE} -faithful %>% ggvis(~eruptions) %>% layer_histograms() -``` - -Modify the fill color and binwidth, and add titles for the axes, since the automatic titles aren't very informative: - -```{r, message = FALSE} -faithful %>% ggvis(~eruptions, fill := "#fff8dc") %>% - layer_histograms(binwidth = 0.25) %>% - add_axis("x", title = "eruptions") %>% - add_axis("y", title = "count") -``` diff --git a/vignettes/data-hierarchy.Rmd b/vignettes/data-hierarchy.Rmd deleted file mode 100644 index 7f0610ba..00000000 --- a/vignettes/data-hierarchy.Rmd +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: "Data hierarchy" ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -``` - -Compared to ggplot2, ggvis has a much richer data hierarchy. In ggplot2, you -could define a data set and aesthetic mappings in the base plot, and override -them in each layer, but since layers could not contain other layers, there were -only ever two levels in the tree. ggvis is more flexible because ggvis nodes -(the equivalent of ggplot2 layers) can contain child nodes. This makes it -possible to have whatever level of hierarchy that is best suited to your plot. - -This is also related to a confusion in ggplot2 where `geom` often were actually -aliases for a geom + combination. For example: - -* `geom_histogram` = `geom_bar` + `stat_bin` -* `geom_smooth` = `geom_smooth` + `stat_smooth` - -In ggvis, there is a clear demarkation between marks (pure drawing) and -layers (transformation + drawing). The low-level functions for drawing a mark start with `emit_`, and then the type of mark. For example: - -* `layer_histograms` = `compute_bin` + `emit_rects` -* `layer_smooths` = `layer_model_predictions` + (`emit_paths` + `emit_ribbons`) - -ggplot2 needed special geoms like `geom_smooth` because the data hierarchy -was not deep enough, and there was no standard way for a stat to take the -output of another stat as it's input, and no way for a stat to feed data to -multiple layers without either creating a custom geom or duplicating the -stat multiple times. - -## Data pipeline - -A ggvis specification creates a data pipeline that flows from the starting -node to all of the leaves (marks). - -## Combining props - -In ggplot2, layers had an `inherit.aes` property which control whether or -not a layer would inherit properties from the parent dataset - this is -particularly useful when writing functions that add annotation to arbitrary -plots - you don't want other properties that the user set interfering with your -layer. In ggvis, that's now a property of `props()`: `props(inherit = FALSE)`. - -To see how ggvis combines properties, you can use the `merge_props` function: - -```{r} -merge_props <- ggvis:::merge_props -merge_props(props(x = ~x), props(y = ~y)) -merge_props(props(x = ~a), props(x = ~b)) -merge_props(props(x = ~a, y = ~a), props(x = ~b, inherit = FALSE)) -``` - -There is currently no way to remove a prop inherited from the parent. See -https://github.com/rstudio/ggvis/issues/37 for progress. - -## Case studies - -### Minard's march - -```{r, eval = FALSE} -ggplot(Minard.cities, aes(x = long, y = lat)) + - geom_path( - aes(size = survivors, colour = direction, group = group), - data = Minard.troops - ) + - geom_point() + - geom_text(aes(label = city), hjust=0, vjust=1, size=4) -``` - -In ggvis, we can make it a little more clear that we have one marked based on -survivors dataset and two marks based on the cities dataset. - -```{r, eval = FALSE} -ggvis(data = NULL, x = ~long, y = ~lat) %>% - layer_points(size = ~survivors, stroke = ~direction, data = Minard.troops) %>% - layer_text(text := ~city, dx := 5, dy := -5, data = Minard.cities) -``` diff --git a/vignettes/ggplot2.Rmd b/vignettes/ggplot2.Rmd deleted file mode 100644 index b51796f0..00000000 --- a/vignettes/ggplot2.Rmd +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "ggvis vs ggplot2" ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -``` - -If you're familiar with ggplot2, learning ggvis shouldn't be too hard - it -borrows from many familiar concepts. Note that ggvis is still very young, -and many of the interfaces are likely to change as we learn more about what -works well. - -* Basic naming conversions: - * layer, geom -> layer function - * stat -> compute function - * `aes()` -> `props()` - * `ggplot()` -> `ggvis()` - -* ggvis has a function interface so you combine components using `%>%`, - not `+` as in ggplot2. - -* Facetting is not currently supported, and when it is supported, it's more - like to resemble [embedded plots](http://vita.had.co.nz/papers/embedded-plots.html) - than facetting in ggplot2. - -* In ggplot2, the definition of a geom was somewhat blurred, because of things - like `geom_histogram()` which combined `geom_bar()` with `stat_bin()`. The - distinction is more clear in ggvis: pure geoms correspond to `emit_*` which - emit marks, and combined geoms and stats correspond to layers. - -* Using `ggvis()` without adding any layers is analogous to `qplot()`. - -* Vega provides a smaller set of scales than ggplot2 (just ordinal, - quantitative, and time), but they are much more flexible than ggplot2 scales, - and offer equivalent functionality. - -* ggplot2 has a two-level hierarchy - you have data and aes specifications in - the plot and in each layer. ggvis provides an unlimited hierarchy - you can - have as many levels as you need (and the data will only be computed once) - -* ggvis makes fewer assumptions about the type of data - data does not have - to be a data frame until it has been processed by a transform. diff --git a/vignettes/ggvis-basics.Rmd b/vignettes/ggvis-basics.Rmd deleted file mode 100644 index 48fd00bb..00000000 --- a/vignettes/ggvis-basics.Rmd +++ /dev/null @@ -1,296 +0,0 @@ ---- -title: ggvis basics -output: - html_document: - toc: true -runtime: shiny ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 3.5, fig.height = 2.5, dpi = 100) -``` - -## Introduction - -The goal of ggvis is to make it easy to build interactive graphics for exploratory data analysis. ggvis has a similar underlying theory to [ggplot2](http://ggplot2.org) (the grammar of graphics), but it's expressed a little differently, and adds new features to make your plots interactive. ggvis also incorporates [shiny](http://www.rstudio.com/shiny/)'s reactive programming model and [dplyr](http://github.com/hadley/dplyr)'s grammar of data transformation. - -The graphics produced by ggvis are fundamentally web graphics and work very differently from traditional R graphics. This allows us to implement exciting new features like interactivity, but it comes at a cost. For example, every interactive ggvis plot must be connected to a running R session (static plots do not need a running R session to be viewed). This is great for exploration, because you can do anything in your interactive plot you can do in R, but it's not so great for publication. We will overcome these issues in time, but for now be aware that we have many existing tools to reimplement before you can do everything with ggvis that you can do with base graphics. - -This vignette is divided into four main sections: - -* Dive into plotting with `ggvis()`. -* Add interactivity with the mouse and keyboard. -* Create more types of graphic by controlling the layer type. -* Build up rich graphics with multiple layers. - -Each section will introduce to a major idea in ggvis, and point to more detailed explanation in other vignettes. - -## `ggvis()` - -Every ggvis graphic starts with a call to `ggvis()`. The first argument is the data set that you want to plot, and the other arguments describe how to map variables to visual properties. - -```{r} -p <- ggvis(mtcars, x = ~wt, y = ~mpg) -``` - -This doesn't actually plot anything because you haven't told ggvis how to display your data. You do that by layering visual elements, for example with `layer_points()`: - -```{r} -layer_points(p) -``` - -(If you're not using RStudio, you'll notice that this plot opens in your web browser. That's because all ggvis graphics are web graphics, and need to be shown in the browser. RStudio includes a built-in browser so it can show you the plots directly.) - -All ggvis functions take the visualisation as the first argument and return a modified visualisation. This seems a little bit awkward. Either you have to create temporary variables and modify them, or you have to use a lot of parentheses: - -```{r} -layer_points(ggvis(mtcars, x = ~wt, y = ~mpg)) -``` - -To make life easier ggvis uses the `%>%` (pronounced pipe) function from the magrittr package. That allows you to rewrite the previous function call as: - -```{r} -mtcars %>% - ggvis(x = ~wt, y = ~mpg) %>% - layer_points() -``` - -Don't worry if this looks a little strange at first. You'll soon get used to it! This style of programming also allows gives you a lot of power when you start creating a lot of power, and allows you to seemlessly intermingle ggvis and dplyr code: - -```{r, message = FALSE} -library(dplyr) -mtcars %>% - ggvis(x = ~mpg, y = ~disp) %>% - mutate(disp = disp / 61.0237) %>% # convert engine displacment to litres - layer_points() -``` - -The format of the visual properties needs a little explanation. We use `~` before the variable name to indicate that we don't want to literally use the value of the `mpg` variable (which doesn't exist), but instead we want we want to use the `mpg` variable inside in the dataset. This is a common pattern in ggvis: we'll always use formulas to refer to variables inside the dataset. - -The first two arguments to `ggvis()` are usually the position, so by convention you can drop `x` and `y`: - -```{r} -mtcars %>% - ggvis(~mpg, ~disp) %>% - layer_points() -``` - -You can add more variables to the plot by mapping them to other visual properties like `fill`, `stroke`, `size` and `shape`. - -```{r} -mtcars %>% ggvis(~mpg, ~disp, stroke = ~vs) %>% layer_points() -mtcars %>% ggvis(~mpg, ~disp, fill = ~vs) %>% layer_points() -mtcars %>% ggvis(~mpg, ~disp, size = ~vs) %>% layer_points() -mtcars %>% ggvis(~mpg, ~disp, shape = ~factor(cyl)) %>% layer_points() -``` - -If you want to make the points a fixed colour or size, you need to use `:=` instead of `=`. The `:=` operator means to use a raw, unscaled value. This seems like something that `ggvis()` should be able to figure out by itself, but making it explicit allows you to create some useful plots that you couldn't otherwise. See the [properties and scales](properties-scales.html) for more details. - -```{r} -mtcars %>% ggvis(~wt, ~mpg, fill := "red", stroke := "black") %>% layer_points() -mtcars %>% ggvis(~wt, ~mpg, size := 300, opacity := 0.4) %>% layer_points() -mtcars %>% ggvis(~wt, ~mpg, shape := "cross") %>% layer_points() -``` - -## Interaction - -As well as mapping visual properties to variables or setting them to specific values, you can also connect them to interactive controls. - -The following example allows you to control the size and opacity of points with two sliders: - -```{r} -mtcars %>% - ggvis(~wt, ~mpg, - size := input_slider(10, 100), - opacity := input_slider(0, 1) - ) %>% - layer_points() -``` - -You can also connect interactive components to other plot parameters like the binwidth of a histogram: - -```{r} -mtcars %>% - ggvis(~wt) %>% - layer_histograms(binwidth = input_slider(0, 2, step = 0.1)) -``` - -Behind the scenes, interactive plots are built with [shiny](http://www.rstudio.com/shiny/), and you can currently only have one running at a time in a given R session. To finish with a plot, press the stop button in Rstudio, or close the browser window and then press Escape or Ctrl + C in R. - -As well as `input_slider()`, ggvis provides `input_checkbox()`, `input_checkboxgroup()`, `input_numeric()`, `input_radiobuttons()`, `input_select()` and `input_text()`. See the examples in the documentation for how you might use each one. - -You can also use keyboard controls with `left_right()` and `up_down()`. Press the left and right arrows to control the size of the points in the next example. - -```{r} -keys_s <- left_right(10, 1000, step = 50) -mtcars %>% ggvis(~wt, ~mpg, size := keys_s, opacity := 0.5) %>% layer_points() -``` - -You can also add on more complex types of interaction like tooltips: - -```{r} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - add_tooltip(function(df) df$wt) -``` - -You'll learn more about complex interaction in the [interactivity](interactivity.html) vignette. - -## Layers - -So far, you seen two layer functions: `layer_points()` and `layer_histograms()`. There are many other layers, and they can be roughly categorised into two types: - -* Simple, which include primitives like points, lines and rectangles. - -* Compound, which combine data transformations with one or more simple layers. - -All layer functions use the plural, not the singular. Think the verb, not the noun: I'm going to layer some points onto my plot. - -### Simple layers - -There are five simple layers: - -* Points, `layer_points()`, with properties `x`, `y`, `shape`, `stroke`, - `fill`, `strokeOpacity`, `fillOpacity`, and `opacity`. - - ```{r} - mtcars %>% ggvis(~wt, ~mpg) %>% layer_points() - ``` - -* Paths and polygons, `layer_paths()`. - - ```{r} - df <- data.frame(x = 1:10, y = runif(10)) - df %>% ggvis(~x, ~y) %>% layer_paths() - ``` - - If you supply a `fill`, you'll get a polygon - - ```{r} - t <- seq(0, 2 * pi, length = 100) - df <- data.frame(x = sin(t), y = cos(t)) - df %>% ggvis(~x, ~y) %>% layer_paths(fill := "red") - ``` - -* Filled areas, `layer_ribbons()`. Use properties `y` and `y2` to control the - extent of the area. - - ```{r} - df <- data.frame(x = 1:10, y = runif(10)) - df %>% ggvis(~x, ~y) %>% layer_ribbons() - df %>% ggvis(~x, ~y + 0.1, y2 = ~y - 0.1) %>% layer_ribbons() - ``` - -* Rectangles, `layer_rects()`. The location and size of the rectangle is - controlled by the `x`, `x2`, `y` and `y2` properties. - - ```{r} - set.seed(1014) - df <- data.frame(x1 = runif(5), x2 = runif(5), y1 = runif(5), y2 = runif(5)) - df %>% ggvis(~x1, ~y1, x2 = ~x2, y2 = ~y2, fillOpacity := 0.1) %>% layer_rects() - ``` - -* Text, `layer_text()`. The text layer has many new options to control the - apperance of the text: `text` (the label), `dx` and `dy` (margin in pixels - between text and anchor point), `angle` (rotate the text), `font` (font - name), `fontSize` (size in pixels), `fontWeight` (e.g. bold or normal), - `fontStyle` (e.g. italic or normal.) - - ```{r} - df <- data.frame(x = 3:1, y = c(1, 3, 2), label = c("a", "b", "c")) - df %>% ggvis(~x, ~y, text := ~label) %>% layer_text() - df %>% ggvis(~x, ~y, text := ~label) %>% layer_text(fontSize := 50) - df %>% ggvis(~x, ~y, text := ~label) %>% layer_text(angle := 45) - ``` - -### Compound layers - -The four most common compound layers are: - -* `layer_lines()` which automatically orders by the x variable: - - ```{r} - t <- seq(0, 2 * pi, length = 20) - df <- data.frame(x = sin(t), y = cos(t)) - df %>% ggvis(~x, ~y) %>% layer_paths() - df %>% ggvis(~x, ~y) %>% layer_lines() - ``` - - `layer_lines()` is equivalent to `arrange()` + `layer_paths()`: - - ```{r} - df %>% ggvis(~x, ~y) %>% arrange(x) %>% layer_paths() - ``` - -* `layer_histograms()` and `layer_freqpolys()` which allows you to explore the - distribution of continuous. Both layers first bin the data with - `compute_bin()` then display the results with either rects or lines. - - ```{r} - mtcars %>% ggvis(~mpg) %>% layer_histograms() - - # Or equivalently - binned <- mtcars %>% compute_bin(~mpg) - binned %>% - ggvis(x = ~xmin_, x2 = ~xmax_, y2 = 0, y = ~count_, fill := "black") %>% - layer_rects() - ``` - -* `layer_smooths()` fits a smooth model to the data, and displays predictions - with a line. It's used to highlight the trend in noisy data: - - ```{r} - mtcars %>% ggvis(~wt, ~mpg) %>% layer_smooths() - - # Or equivalently - smoothed <- mtcars %>% compute_smooth(mpg ~ wt) - smoothed %>% ggvis(~pred_, ~resp_) %>% layer_paths() - ``` - - You can control the degree of wiggliness with the span parameter: - - ```{r} - span <- input_slider(0.2, 1, value = 0.75) - mtcars %>% ggvis(~wt, ~mpg) %>% layer_smooths(span = span) - ``` - -You can learn more about layers in the [layers](layers.html) vignette. - -## Multiple layers - -Rich graphics can be created by combining multiple layers on the same plot. This easier to do: just layer on multiple elements: - -```{r} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_smooths() %>% - layer_points() -``` - -You could use this approach to add two smoothers with varying degrees of wiggliness: - -```{r} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_smooths(span = 1) %>% - layer_smooths(span = 0.3, stroke := "red") -``` - -You'll learn more about building up rich hierarchical graphics in [data hierarchy](data-hierarchy.html). - -## More details - -There are other optional components that you can include: - -* `scales`, to control the mapping between data and visual properties. - These are described in the [properties and scales](properties-scales.html) vignette. - -* `legends` and `axes` to control the appearance of the guides produced by - the scales. See the [axes and legends](axes-legends.html) vignette for more details. diff --git a/vignettes/interactivity.Rmd b/vignettes/interactivity.Rmd deleted file mode 100644 index 09e02ca5..00000000 --- a/vignettes/interactivity.Rmd +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Interactivity -output: - html_document: - toc: true -runtime: shiny ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 3.5, fig.height = 2.5, dpi = 100) -``` - -**Note: If you're viewing the HTML version of this document generated with knitr, the examples will have their interactive features disabled. You'll need to run the code in R to see and use the interactive controls.** - -Ggvis interactivity is built on top of Shiny's reactive programming -model. It's possible to use ggvis without understanding how Shiny works, -but you'll be limited to relatively simple interactions. The first part of -this vignette describes __basic interactive controls__, which provide a quick -and easy way to add basic interactivity to a plot. They are not very flexible, -but they cover the most common interactive needs and you don't need to know -anything about Shiny to use them. - -The second part of this vignette shows you how to __embedding a ggvis in a Shiny -app__. This gives you complete freedom to make any component of the plot -interactive, to display multiple plots on one page, and to freely arrange -controls. The downside is that you'll need more code, and you'll need at -least a basic understanding of Shiny. If you're not already familiar with -how Shiny works, I recommend that you first read through the -[Shiny tutorial](http://rstudio.github.io/shiny/tutorial/) - -## Basic interactive controls - -A plot with basic interactive controls looks very similar to a static plot. -You just replace constant values with functions that produce interactive -controls like `input_slider()`: - -```{r} -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_smooths(span = input_slider(0.5, 1, value = 1)) %>% - layer_points(size := input_slider(100, 1000, value = 100)) -``` - -As well as `input_slider()`, which produces a slider (or a double-ended range -slider), there are a number of other interactive controls: - -* `input_checkbox()`: a check-box -* `input_checkboxgroup()`: a group of check boxes -* `input_numeric()`: a spin box -* `input_radiobuttons()`: pick one from a set options -* `input_select()`: create a drop-down text box -* `input_text()`: arbitrary text input - -Note that all interactive inputs start with `input_` so that you can always use -tab completion to remind you of the options. - -Here is an example of a plot that uses both a slider and a select box: - -```{r, eval=FALSE} -mtcars %>% ggvis(x = ~wt) %>% - layer_densities( - adjust = input_slider(.1, 2, value = 1, step = .1, label = "Bandwidth adjustment"), - kernel = input_select( - c("Gaussian" = "gaussian", - "Epanechnikov" = "epanechnikov", - "Rectangular" = "rectangular", - "Triangular" = "triangular", - "Biweight" = "biweight", - "Cosine" = "cosine", - "Optcosine" = "optcosine"), - label = "Kernel") - ) -``` - -### Arguments - -The arguments differ slightly depending on the type of input, and are documented -in the individual function documentation. All input sliders share three common -arguments: - -* `label`: an informative text label displayed next to the control - -* `id`: a unique identifier for the control - this is randomly assigned and - you should only need to override in exceptional circumstances. - -* `map`: a function that enables you to remap the output of the input to - something appropriate for your graphic. - -`map` is the most commonly argument used as it allows you to translate the value -recieved from the input to something that's meaningful for your plot. For -example, many parameters of statistical models are best expressed on a log -scale. You can use `map` in conjunction with an slider to make multiple orders -of magnitude easily accessible from a single slider. - -```{r, eval = FALSE} -input_slider(-5, 5, label = "lambda", map = function(x) 10 ^ x) -``` - -### Multiple outputs - -There are two ways to have an interactive input control multiple settings on -the plot. - -1. Use the regular property inheritance structure: - - ```{r} - mtcars %>% - ggvis(~wt, ~mpg, size := input_slider(10, 1000)) %>% - layer_points(fill := "red") %>% - layer_points(stroke := "black", fill := NA) - ``` - -2. Create the input and assign it to a variable: - - ```{r} - slider <- input_slider(10, 1000) - mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points(fill := "red", size := slider) %>% - layer_points(stroke := "black", fill := NA, size := slider) - ``` - - This is a little more typing, but is more flexible. - -Compare the following two plots. In the first plot, one slider is created and -used for both layers - it controls the size of both the red and the black -points. In the second plot, you get two independent sliders which allow you to -control the size of the red and black points independently. - -```{r} -slider <- input_slider(100, 1000) -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points(size := slider) %>% - layer_points(fill := "red", opacity := 0.5, size := slider) - -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points(size := input_slider(100, 1000, label = "black")) %>% - layer_points(fill := "red", size := input_slider(100, 1000, label = "red")) -``` - -### Property mappings - -When you map a slider to a property, you have four basic options: - -* constant, unscaled -* constant, scaled -* variable, unscaled -* variable, scaled - -If you just assign the input in `props()`, like `props(size = input_slider())`, -you'll get a constant, unscaled property. To gain more control you can use -`prop()`: `props(prop("size", input_slider()))`. - -You'll need to do this if you want to: - -* select a variable to plot based on a dropdown: - `prop(x = input_select(c("disp", "wt")), constant = FALSE)` - -* annotate the plot in the data space: - `prop(x = input_slider(min(mpg$wt), max(mpg$wt)), scale = TRUE)` - -You can read more about these options in the __properties and scales__ vignette. - -### Limitations - -Currently, interactive inputs can only be used in two places: - -* as arguments to transforms: `layer_smooths(span = input_slider(0, 1))` -* as properties: `props(size = input_slider(10, 1000))` - -This means that interactive inputs can only modify the data, not the underlying -plot specification. In other words, with only basic interactivity there's no -way to add or remove layers, or switch between different datasets. This is a -reasonable limitation because if you're doing exploration you can always create -a new ggvis with R code, or if you're polishing a plot for presentation, you -can embed it in a Shiny app and gain full control over the plot. - -### Compared to Shiny - -If you're familiar with Shiny, you'll notice that these functions have very -similar equivalents: `sliderInput()`, `selectInput()` and so on. There are two -main differences: - -* the argument order has been tweaked so that you can create a basic control - with minimal arguments. The `label` is optional because if you're creating a - plot for yourself, you usually remember what the controls do; and each control - is assigned a random `id` so you don't need to think one up. - -* interactive input are not necessarily created in a reactive context, so they - can not return reactives. Instead, they return delayed reactives, which are - activated and connected together when the plot is displayed. - -## Shiny apps - -If you know how to create a Shiny app already, adding a ggvis plot is easy. In -`server.r`, create a ggvis object, and call `bind_shiny()`. When called in a pipe, the arguments are the names of the plot and control placeholders. - -```{r, eval = FALSE} -# A reactive expression wrapper for input$size -input_size <- reactive(input$size) - -mtcars %>% - ggvis(~disp, ~mpg, size := input_size) %>% - layer_points() %>% - bind_shiny("ggvis", "ggvis_ui") -``` - -Create `ui.r` as usual, using `ggvisOutput()` to place the ggvis plot on the -page. - -```{r, eval = FALSE} -shinyUI(pageWithSidebar( - sidebarPanel( - sliderInput("size", "Area", 10, 1000), - ), - mainPanel( - uiOutput("ggvis_ui"), - ggvisOutput("ggvis") - ) -)) -``` - -There are a couple of examples in the `demo/apps` directory. diff --git a/vignettes/layers.Rmd b/vignettes/layers.Rmd deleted file mode 100644 index f43916a4..00000000 --- a/vignettes/layers.Rmd +++ /dev/null @@ -1,250 +0,0 @@ ---- -title: Layers ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 3.5, fig.height = 2.5, dpi = 100) -``` - -In ggvis, there are two types of layers. Simple layers correspond directly to vega marks and represent geometric primitives like points, lines and rectangles. Compound layers combine data transformations with one or more simple layers. - -## Marks - -Marks are the fundamental building block. Each type of mark represents a different type of geometric object, and so in some sense they are the equivalent of geoms in ggplot2. However, there are a far fewer marks than geoms because marks tend to be more capable, and because they never perform any statistical transformation. - -Most of the time you don't use marks directly - you instead use their layer wrappers. That's because most of the time you don't want to think about the difference between simple and compound layers - you just want to make a plot. But if you want to understand more deeply how things work, or create your own layer functions, it's important to understand the distinction. - -`ggvis` exposes -[five vega marks](https://github.com/trifacta/vega/wiki/Marks#color-references) -that have very similar ggplot2 equivalents: - -* `mark_area()` = `geom_ribbon()`, `geom_area()` -* `mark_path()` = `geom_path()`, `geom_line()` -* `mark_rect()` = `geom_rect()`, `geom_bar()`, `geom_tile()` -* `mark_point()` = `geom_point()` -* `mark_text()` = `geom_text()` - -There are two marks that have no equivalent in ggplot2: - -* `mark_arc()` allows you to draw arcs. You could accomplish something - similar in ggplot2 with `geom_rect()` with `coord_polar()` but it was - relatively inflexible and required contorting your brain a bit. - -* `mark_image()` allows you to place arbitrary images on a plot. There is - currently little additional support for this in ggvis, so you'll need to - make sure the images are publicly available somewhere. If you've found - a compelling use-case for `layer_image()`, let us know so we can consider - how to better support it. - -And two vega marks that are not currently implemented in ggvis: - -* Support for the group mark will be added in a future major release that - will add support for facetting/subplots. - -* I can't currently see any use for the path mark, which takes svg path - specifications as input. - -All marks take two optional arguments which are only needed if you want to -override the values inherited from parent: - -* `props`, a `props()` object used to add any custom override for this layer -* `data`, an optional dataset to override the data inherited from the parent - -## Adding a layer to a plot - -For example, the following two plots are equivalent. In the first one, the -data and props are defined at the top level and inherited by the mark, and in -the second, they are defined in the mark itself. Note that the order of the -arguments to `ggvis()` and the mark function are different: this is because -you'll usually set the data in top-level plot object, and usually only override -props in the mark. - -```{r} -mtcars %>% ggvis(x = ~wt, y = ~mpg, stroke := "red") %>% layer_points() -mtcars %>% ggvis() %>% layer_points(x = ~wt, y = ~mpg, stroke := "red") -``` - -## Mark details - -The following sections describe particular details related to individual marks. - -### `layer_rects` - -Must set two of `x`, `x2`, and `width`, and two of `y`, `y2` and `height`. - -If you have an ordinal scale, set width and/or height to `prop_band()` to -occupy the complete band corresponding to that categorical value. - -```{r} -hec <- as.data.frame(xtabs(Freq ~ Hair + Eye, HairEyeColor)) - -hec %>% - ggvis(~Hair, ~Eye, fill = ~Freq) %>% - layer_rects(width = band(), height = band()) %>% - scale_nominal("x", padding = 0, points = FALSE) %>% - scale_nominal("y", padding = 0, points = FALSE) -``` - -### `layer_paths` - -`layer_path` produces lines if fill is empty, and polygons if it is set to a -value. - -```{r} -df <- data.frame(x = c(1, 1, 2, 2), y = c(2, 1, 1, 2)) -df %>% ggvis(~x, ~y, stroke := "red") %>% layer_paths() -# Add a fill colour to make it a polygon -df %>% ggvis(~x, ~y, fill := "red") %>% layer_paths() -``` - -You can not currently set the component of lines to different colours: -track progress at https://github.com/trifacta/vega/issues/122. - -To create a line that spans the complete range of the plot, use `prop_group()`: - -```{r, eval = FALSE} -ggvis() %>% - layer_points(x = ~disp, y = ~wt, data = mtcars) %>% - layer_paths(x := 0, y = ~mean(mtcars$wt, x2 := prop_group())) %>% - layer_paths(x = ~mean(mtcars$disp), y := 0, y2 := prop_group()) -``` - -Note that this won't work because `prop_group()` hasn't been written yet: track -progress at https://github.com/rstudio/ggvis/issues/38. - -### `layer_ribbons` - -You need to set two of `y`, `y2` and `height`: - -```{r} -df <- data.frame(x = 1:10, y = (1:10) ^ 2) -df %>% ggvis(~x, ~y, y2 := 0) %>% layer_ribbons() - -# Set height in pixels -df %>% ggvis(~x, ~y, height := 20) %>% layer_ribbons() -``` - -Height can only be mapped to a constant, because it does not have an obvious -scale associated with it. You could force height to use the `y` scale, but that -doesn't work - the area hangs below the y line, and increasing the value of -height makes the area narrower! What's going on is that the underlying graphics -device has (0, 0) in the top-left corner, and so the y-scale is upside down. As -you increase height, it's mapped like a y variable so bigger values are further -away. - -```{r} -df %>% ggvis(~x, ~y, prop("height", 80, scale = "y")) %>% layer_ribbons() - -df <- data.frame(x = 1:10, y = (1:10) ^ 2) -df %>% ggvis(~x, ~y) %>% - layer_ribbons(prop("height", input_slider(0, 100), scale = "y")) %>% - layer_paths(stroke := "red", strokeWidth := 10) -``` - -If you want to set the height in data units, you need to -compute the offsets yourself: - -```{r} -df %>% ggvis(~x, y = ~y - 2, y2 = ~y + 2) %>% layer_ribbons() -``` - -The distinction between dimension and location is important in other graphics system, and a grid vignette `vignette("locndimn", package = "grid")` has a little more information about how things work in grid. - -## Grouping - -In ggplot2, grouping was a special aesthetic; in ggvis, grouping is a data -transformation: use `group_by()` to split your data up into pieces given a -specified variable, or `auto_split()` to split up by any categorical variable included in the plot: - -```{r} -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - group_by(cyl) %>% - layer_paths() - -mtcars %>% ggvis(~wt, ~mpg) %>% - layer_points() %>% - auto_group() %>% - layer_paths() -``` - -Some layers, like `layer_line()`, include `auto_split()` so will split automatically: - -```{r} - -mtcars %>% - dplyr::mutate(cyl2 = factor(cyl)) %>% - ggvis(~wt, ~mpg, stroke = ~cyl2) %>% - layer_lines() -``` - -## Compound layers - -Simple layers map directly to vega's primitive drawing functions (marks). Compound layers combine data transformation and simple layers (potentially multiple of each) to more sophisticated graphics. For example: - -* `layer_histogram()` = `transform_bin()` + `mark_rect()` -* `layer_freqpoly()` = `transform_bin()` + `mark_path()` -* `layer_smooth()` = `transform_smooth()` + (`mark_path()` + `mark_area()`) - -All layers start with `layer_`. The source is usually relatively simple - the complexity generally comes when figuring out how to map properties supplied to the layer to individual marks: - -```{r} -layer_smooths -layer_histograms -``` - -If you find yourself using a set of marks commonly, it might be worth writing -your own layer function. - -## Conversion from ggplot2 - -The following list provides a conversion from ggplot2 geoms to vega marks. -However, because ggvis currently provides few transformations, many translations -don't currently exists - but they are on the roadmap and will be added over -time. - -* `geom_abline` -* `geom_area` = `layer_ribbons` with `y = ~0` -* `geom_bar` = `layer_rects` with `y = ~ 0, width = band()` -* `geom_bin2d` = `layer_rects` + `transform_bin2d` -* `geom_blank` -* `geom_boxplot` -* `geom_contour` -* `geom_crossbar` -* `geom_density` = `layer_densities` = `layer_paths` + `compute_density` -* `geom_density2d` -* `geom_dotplot` -* `geom_errorbar` -* `geom_errorbarh` -* `geom_freqpoly` -* `geom_hex` -* `geom_histogram` = `layer_histograms` = `layer_bar` + `transform_bin` -* `geom_hline` = = `layer_paths` + `x2 ~ prop_group("width"))`. -* `geom_jitter` -* `geom_line` = `layer_lines` = `layer_paths` + `compute_sort` -* `geom_linerange` -* `geom_map` -* `geom_path` = `layer_paths` -* `geom_point` = `layer_points` -* `geom_pointrange` -* `geom_polygon` = `layer_paths` -* `geom_quantile` = `layer_paths` + `compute_quantreg` -* `geom_raster` -* `geom_rect` = `layer_rects` -* `geom_ribbon` = `layer_areas` -* `geom_rug` -* `geom_segment` -* `geom_smooth` = `layer_smooths` = `layer_ribbon` + `layer_paths` + `compute_smooth` -* `geom_step` = `layer_paths` + `transform_step` -* `geom_text` = `layer_text` -* `geom_tile` = `layer_rects` + `width = band(), height = band())` -* `geom_violin` -* `geom_vline` = `layer_paths` + `y2 = prop_group("height")` diff --git a/vignettes/overview.Rmd b/vignettes/overview.Rmd deleted file mode 100644 index 14f968ea..00000000 --- a/vignettes/overview.Rmd +++ /dev/null @@ -1,73 +0,0 @@ ---- -title: "ggvis overview" -output: html_document -runtime: shiny ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 2.5, fig.height = 1.5, dpi = 100) -``` - -ggvis is a data visualization package for R which lets you: - -* Declaratively describe data graphics with a syntax similar in spirit to - ggplot2. - -* Create rich interactive graphics that you can play with locally in Rstudio - or in your browser. - -* Leverage [shiny](http://www.rstudio.com/shiny/)'s infrastructure to publish - interactive graphics usable from any browser (either within your company - or to the world). - -The goal is to combine the best of R (e.g. every modelling function you can imagine) and the best of the web (everyone has a web browser). Data manipulation and transformation are done in R, and the graphics are rendered in a web browser, using [Vega](https://github.com/trifacta/vega/). For RStudio users, ggvis graphics display in a viewer panel, which is possible because RStudio is a web browser. - -## Examples of ggvis graphics - -Histogram: - -```{r, echo = FALSE, fig.width = 4} -# Histogram -faithful %>% ggvis(~eruptions, fill := "#ffffdd", fill.hover := "#eebbbb") %>% - layer_histograms(binwidth = 0.2) %>% - add_axis("x", title = "eruptions") %>% - add_axis("y", title = "count") -``` - -Scatterplot with smooth curve and interactive control: - -```{r, echo = FALSE, fig.width = 3, fig.height = 3} -# Scatter plot with model fit line -mtcars %>% - ggvis(~wt, ~mpg) %>% - layer_points() %>% - layer_smooths(span = input_slider(0.2, 1, 0.75, step = 0.05, - label = "Smoothing span")) -``` - -## Getting started with ggvis - -* See some [recipes](cookbook.html) for common tasks. -* Learn [ggvis basics](ggvis-basics.html). -* Read more about [interactive graphics](interactivity.html). - -## More advanced topics - -* How to control [axes and legends](axes-legends.html). -* How to use [properties and scales](properties-scales.html). -* Learn about [layers](layers.html). -* Plumbing: about ggvis's [data hierarchy](data-hierarchy.html). - -## More about ggvis - -* Differences and similarities to [ggplot2](ggplot2.html). -* The relationship between ggvis and [Vega](vega.html). - diff --git a/vignettes/properties-scales.Rmd b/vignettes/properties-scales.Rmd deleted file mode 100644 index 912bfede..00000000 --- a/vignettes/properties-scales.Rmd +++ /dev/null @@ -1,368 +0,0 @@ ---- -title: Properties and scales ---- - - - -```{r, echo = FALSE, message = FALSE} -library(knitr) -library(ggvis) -opts_chunk$set(comment = "#>", error = FALSE, tidy = FALSE) -opts_chunk$set(fig.width = 3.5, fig.height = 2.5, dpi = 100) -``` - -Understanding how properties and scales work in ggvis an important step to -mastering basic static plots, and is also necessary for great interactive -graphics. - -In this chapter, you will learn: - -* the convenient `props()` wrapper which makes the most common types of - property mappings available through a concise interface - -* the `prop()` function, which is more verbose, but gives you full control - over all options - -* what scales do, how properties and scales are connected, how you can - override the defaults. - -Note that unlike ggplot2, scales do not control the appearance of their guides: -see the [axes and legends](axes-legends.html) vignette for how to customise their display. - -## The `props()` wrapper - -Every ggvis mark is associated with a set of properties that governs how it is displayed. These properties can be constant values (like 5, "blue", or "square"), or mapped to variables in your dataset. ggplot2 syntax made a distinction between mapping variables and setting constants. For example, in ggplot2, you might say: - -```{r eval = FALSE} -geom_point(aes(x = wt, y = mpg), colour = "red", size = 5) -``` - -But in ggvis, everything is a property: - -```{r, eval = FALSE} -layer_paths(x = ~wt, y = ~mpg, stroke := "red", strokeWidth := 5) -``` - -This section introduces `props()`, a convenient function for creating property objects and binding them to property names. The next chapter shows you how to create the property objects by hand, giving you more control over the specification at the cost of some extra typing. - -### Mapping vs setting (scaled vs unscaled) - -In a data graphic, there is a mapping between values and visual properties. A value is something like 5, or "red", or the numbers in a column of a data frame. A visual property is something like the x-position, y-position, size, or color of a point, rectangle, or other visual object. - -Compared to ggplot2, the controls in ggvis may be a little confusing. However, ggplot2 has a number of special cases that are handled under the hood. Once you get the hang of `props()`, you should find it simpler than `aes()` and various ways of setting aesthetics in ggplot2. - -The `props()` function creates objects that govern the relationship between values and properties. One important characteristic is whether the value-property relationship is *scaled* or *unscaled*. These are sometimes called *mapping* (for scaled values) and *setting* (unscaled values). When the relationship is scaled, the data values go through a mapping function that results in values in the visual property space. - -For example, suppose that you want to use a variable in a data set on the x axis, and the data values are numbers from 55 to 75. If the relationship is scaled, then the data value 55 is typically mapped to an x position on the left side of the plot, the data value 75 is mapped to an x position on the right side of the plot, and values in between are linearly mapped somewhere between those positions. - -If the relationship is unscaled, then the data values 55 to 75 would be used directly by the rendering engine. In the case of ggvis and Vega, a value of 55 means "55 pixels from the left edge", and a value of 75 means "75 pixels from the left edge". No matter how the plot is resized, those pixel positions would remain the same. - -The `props()` function uses the `=` operate for mapping (scaled), and the `:=` operator for setting (unscaled). It also uses the `~` operator to indicate that an expression should be evaluated in the data (and in ggvis, the data can change); without the `~` operator, the expression is evaluated immediately in the current environment. Generally speaking, you'll want to use `~` for variables in the data, and not use it for constant values. - -Here are some examples of how to use `=` (mapping) and `:=` (setting), as well as `~` (evaluated in data) or not. - -* `props(x = ~displ, y = ~mpg)`: map engine displacement (in the data) to x and miles - per gallon to y - -* `props(stroke := "red", fill := "blue")`: set the stroke colour to red and the - fill colour to blue. - -* `props(x = ~displ, y := 10)`: map displacement to xand set the y position to 10 pixels (for unscaled y values, the origin is at the top). - -Those examples follow a common pattern: `=` is always scaled, and `:=` is never scaled. `~` is always used with the name of the variable. What if you try the opposite? - -* `props(x = 0)`: sets the x position to the data value 0 - -It's also possible provide a scaled constant instead of a raw constant. -That's useful when you want to label different layers in a plot: - -```{r, eval = FALSE} -mtcars %>% ggvis(x = ~wt, y = ~mpg) %>% - layer_points() %>% - layer_model_predictions(model = "lm", stroke = "lm") %>% - layer_smooths(stroke = "loess") -``` - -(Note: this isn't currently supported in ggvis because of a limitation -of vega. See https://github.com/rstudio/ggvis/issues/29 for progress.) - -### Valid properties - -Not all marks support all properties. The complete list of all properties is -available in `?marks`, and mark functions will check that you've supplied them -valid properties, and will endeavour to provide you a helpful suggestion: - -```{r, eval = FALSE} -mtcars %>% ggvis() %>% layer_lines(strke = ~cyl) -#> Error: Unknown properties: strke. Did you mean: stroke? -mtcars %>% ggvis(strke = ~cyl) %>% layer_lines() -#> Error: Unknown properties: strke. Did you mean: stroke? -``` - -### Capture of local variables - -Variable properties can refer to both variables in the dataset and variables in -the local environment: - -```{r} -df <- data.frame(x = 1:10) -f <- function(n) { - df %>% ggvis(x = ~x, y = ~x ^ n) %>% layer_paths() -} -f(1) -f(2) -f(4) -``` - -Technically, ggvis uses the environment captured by the formula when it is -created, which may be important if you're generating formulas in one function -and using them in another. You can always override the environment by calling -`prop()` and supplying the `env` argument. - -## `prop()` - -A prop has two key properties: - -* value: which can be a constant, the name of a variable (or an expression - involving one or more variables), or an interactive input. An interactive - input must yield either a constant, or an variable name/expression. - -* the scale: if scaled, a vega scale is in charge of converting the data - value to something that makes sense as a visual property. If unscaled, the - value is used as is. - - Unscaled is the equivalent of using `scale_identity` in ggplot2. - -Type | Scaled | Common use | In props -------------|--------|------------------------- -variable | yes | Map variable to property | `x = ~mpg` -variable | no | Variable already contains visual values | `x := ~colour` -constant | yes | Annotation position in data space | `x = 1` -constant | no | Pixel location, or exact colour | `x := 1` - -### Special evaluation and variables - -`prop()` doesn't do any special evaluation which means that you if you want a -variable, you need to supply the name of a property, and a quoted expression or a one-sided formula: - -```{r} -prop("x", quote(mpg)) -prop("y", ~cyl) -``` - -If you have the name of a variable as a string, you can convert it a name with -`as.name()`: - -```{r} -var <- "mpg" -prop("x", as.name(var)) -``` - -If you have an R expression as a string, `parse()` it then extract the first -element of the result: - -```{r} -expr <- "mpg / wt" -prop("x", parse(text = expr)[[1]]) -``` - -## Properties -> scales - -Like in ggplot2, scales control the mapping between data values and values -interpreted by the drawing device. Scales are added to the top-level plot -specification and are usually created with `dscale` (short for default scale): - -```{r} -# Override the default data limits: -mtcars %>% ggvis(~disp, ~wt) %>% - layer_points() %>% - scale_numeric("x", domain = c(50, 500), nice = FALSE) %>% - scale_numeric("y", domain = c(0, 6), nice = FALSE) -``` - -Compared to ggplot2, ggvis has far fewer scales (3 vs 70), with each function -doing much more. The three basic scales in ggvis, corresponding to the -[three basic vega scales][vega-scales] are: - -* `scale_quantitative`: for quantitative, numeric values -* `scale_ordinal`: for qualitative, categorical values -* `scale_time`: for date/time values - -The vega scales are in turn relatively simple wrappers for -[D3 scales][d3-scales] so if you can't find the details in these docs, or in -the vega docs, you may need to look in the D3 docs. Fortunately the arguments -are by and large named the same across all three systems, although ggvis uses -underscores while vega and D3 use camelCase. - -Each (scaled) property needs a scale. By default, scales are added so that -every scaled property gets a scale with the same name as the property (with a -few exceptions `y2` to `y`, `x2` to `x`, `fillOpacity` and `strokeOpacity` to -`opacity` and so on.). See `?add_default_scales` for details. - -### Scale arguments - -The scales share the following arguments: - -* `name`: a string identifier for the scale. By default, this is the name of the - property it is associated with - i.e. the scale for the x values is called - "x", but it doesn't have to be, and the examples below show some cases where - you need this extra flexibility. - -* `domain`: the input data values to the scale. If left blank, these will be - learned from the properties that use this scale. But you can override it - if you want to expand or restrict, or you want to match domains across - multiple plots so that they're easier to compare. `domain` is equivalent to - `limits` in R graphics. For quantiative scales, you can use a missing value - to only constrain one side of the domain. - -* `range`: the output visual values from the scale. For quantiative scales this - is usually a vector of length two, for ordinal scales, it's a vector the same - length as the domain. Vega interprets some special values: "width", "height", - "shapes", "category10" (10 categorical colours). - -* `reverse`: a boolean flag that will flip the order of the range. - -`scale_quantitative` and `scale_time` also share a few other properties: - -* `nice`: use nice axis labels? The algorithm is described in the - [D3 document][d3-nice] - -* `zero`: include a zero in the scale? - -* `clamp`: clamp any values outside the domain to the min/max? - -### Default scales - -Because the range of a scale is usually determined by the type of variable, -ggvis provides the `dscale` function to automatically retrieve a default scale -given a property name and variable type: - -```{r, eval = FALSE} -scale_numeric(vis, "x") -scale_numeric(vis, "y") -scale_nominal(vis, "shape") -``` - -You can also provide other arguments to the underlying scale: - -```{r, eval = FALSE} -scale_numeric(vis, "x", domain = c(10, 100)) -scale_numeric(vis, "x", trans = "log") -``` - -So `dscale()` is usually a better way to create new scales that starting from -the underlying scale objects. - -### Custom scales - -You can add your own scales for properties that don't otherwise have defaults. -For example, imagine you wanted to use the font of a label to represent some -data. There's no default scale for font, but you could create one yourself: - -```{r} -df <- data.frame(x = runif(5), y = runif(5), - labels = c("a", "b", "b", "a", "b")) -df %>% ggvis(~x, ~y, text := ~labels, font = ~labels, fontSize := 40) %>% - layer_text() %>% - scale_ordinal("font", range = c("Helvetica Neue", "Times New Roman")) -``` - -Note the use of `text := ~labels`: we don't want to scale the labels - the raw values already make sense in the visual space. - -### Multiple scales for one property - -Generally, you will override the default name of a scale in order to use -more scales than the default. You could do this in order to create a dual-axis -chart (which is generally a bad idea - read [this paper][dual-axis] for more details). -If you do this, you will also need to add a scale object. - -```{r} -mtcars %>% ggvis(y = ~mpg) %>% - layer_points(prop("x", ~disp, scale = "xdisp")) %>% - layer_points(prop("x", ~wt, scale = "xwt"), fill := "blue") %>% - add_axis("x", "xdisp", orient = "bottom") %>% - add_axis("x", "xwt", orient = "bottom", offset = 20, - properties = axis_props(labels = list(fill = "blue"))) -``` - -### Multiple properties for one scale - -You could also force ggplot2 to use the same scale for properties that would -otherwise use different scales. I'm not sure of a useful example of this, -except to force `stroke` and `fill` to use the same scale: - -```{r} -df <- data.frame(x = 1:5, y = 1:5, a = runif(5), b = -runif(5)) - -df %>% - ggvis(x = ~x, y = ~y, stroke = ~a, fill = ~b, - strokeWidth := 5, size := 1000) %>% - layer_points() %>% - add_legend("stroke", properties = legend_props(legend = list(y = 50))) - -df %>% - ggvis(x = ~x, y = ~y, stroke = ~a, prop("fill", ~b, scale = "stroke"), - strokeWidth := 5, size := 1000) %>% - layer_points() %>% - add_legend("stroke", properties = legend_props(legend = list(y = 50))) -``` - -In this case we don't need to manually add the correct scale, because ggvis -has detected it for us automatically. - -### Property values - -Vega renders either svg or canvas, but fortunately most properties are shared -across svg or canvas. The following list describes what the property values -mean and the set of allowable values. - -* `x`, `x2`, `width`, `y`, `y2`, `height`, `strokeWidth`, `innerRadius`, - `outerRadius`: pixels. Note that by convention (0, 0) is located in the - top-left, so y values are relative to the top of the screen and x values - are relative to the left of the screen (as opposed to R where (0,0) is on - the bottom right). Pixel positions should be greater than 0. - -* `size`: area, in pixels. Greater than 0. - -* `opacity`, `fillOpacity`, `strokeOpacity`: a number between 0 and 1 - -* `stroke`, `fill`: colours - -* `startAngle`, `endAngle`: angle in radians - -* `interpolate`: "linear", "step-before", "step-after", "basis", "basis-open", - "cardinal", "cardinal-open", "monotone". See the [D3 docs][interpolate-docs] - for what they mean. - -* `tension`: a number between 0 and 1 that controls a tension parameter to - some interpolants.See the [D3 docs][tension-docs] for more details. - -* `url`: a url. - -* `align`: "left", "right", "center". - -* `baseline`: "top", "middle", "bottom" - -* `text`: a string - -* `dx`, `dy`: pixel offsets from anchor point - -* `angle`: an angle in degrees - -* `font`: the name of a font available from the browser. - -* `fontWeight`: a font weight, as a string ("normal", "bold", "lighter", - "bolder") or number (100, 200, 300, 400, 500, 600, 700, 800, 900). - -* `fontStyle`: "normal", "italic", "oblique" - - -[dual-axis]: https://www.lri.fr/~isenberg/publications/papers/Isenberg_2011_ASO.pdf -[interpolate-docs]: https://github.com/mbostock/d3/wiki/SVG-Shapes#wiki-line_interpolate -[tension-docs]: https://github.com/mbostock/d3/wiki/SVG-Shapes#wiki-line_tension -[d3-nice]: https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear_nice -[vega-scales]: https://github.com/trifacta/vega/wiki/Scales -[d3-scales]: https://github.com/mbostock/d3/wiki/Scales diff --git a/vignettes/vega.Rmd b/vignettes/vega.Rmd deleted file mode 100644 index e2731951..00000000 --- a/vignettes/vega.Rmd +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: ggvis and Vega/D3 -output: - html_document ---- - - -While ggvis is built on top of vega, which in turn borrows many ideas from d3, -it is designed more for data exploration than data presentation. This means that -ggvis makes many more assumptions about what you're trying to do: this allows -it to be much more concise, at some cost of generality. - -The main difference to vega is that ggvis provides a tree like structure -allowing properties and data to be specified once and then inherited by -children. - -Vega plays a similar role to ggvis that grid does to ggplot2. That means that -you shouldn't have to know anything about vega to use ggvis effectively, and -you shouldn't have to refer to the vega docs to solve common problems. However, -some knowledge of how vega works is likely to be necessary when you start -doing more complex layouts or when you start pushing the limits of the ggvis -DSL. \ No newline at end of file