Skip to content

Update vignettes #642

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jul 15, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: plotly
Title: Create Interactive Web Graphics via 'plotly.js'
Version: 4.0.0
Version: 4.0.1
Authors@R: c(person("Carson", "Sievert", role = c("aut", "cre"),
email = "[email protected]"),
person("Chris", "Parmer", role = c("aut", "cph"),
Expand Down
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export(groups)
export(groups.plotly)
export(hide_colorbar)
export(knit_print.plotly_figure)
export(last_plot)
export(layout)
export(mutate)
export(mutate_)
Expand Down
25 changes: 18 additions & 7 deletions NEWS → NEWS.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,29 @@
4.0.0
# 4.0.1 -- 14 June 2016

BREAKING CHANGES & IMPROVEMENTS:
## BUG FIXES

* Formulas (instead of plain expressions) are now required when using variable mappings. For example, `plot_ly(mtcars, x = wt, y = mpg, color = vs)` should now be `plot_ly(mtcars, x = ~wt, y = ~mpg, color = ~vs)`. This is a major breaking change, but it is necessary to ensure that evaluation is correct in all contexts (as a result, `evaluate` argument is now deprecated as it is no longer needed). It also has the benefit of being easier to program with (i.e., writing your own custom functions that wrap `plot_ly()`). For more details, see the [lazyeval vignette](https://github.com/hadley/lazyeval/blob/master/vignettes/lazyeval.Rmd)
* The data structure used to represent plotly objects is now an htmlwidget object (instead of a data frame with a special attribute tracking visual mappings). As a result, the `as.widget()` function has been deprecated, and [serialization/memory leak problems](https://github.com/rstudio/shiny/issues/1151) are no longer an issue. This change also implies that arbitrary data manipulation functions can no longer be intermingled inside a plot pipeline, but plotly methods for dplyr's data manipulation verbs are now provided (see `?plotly_data` for examples).
* Duplicated values of positional attributes are no longer removed (bug was introduced in v4.0.0).

## OTHER CHANGES

* Upgraded to plotly.js v1.14.2 -- https://github.com/plotly/plotly.js/releases/tag/v1.14.2

# 4.0.0 -- 13 June 2016

## BREAKING CHANGES & IMPROVEMENTS:

* Formulas (instead of plain expressions) are now required when using variable mappings. For example, `plot_ly(mtcars, x = wt, y = mpg, color = vs)` should now be `plot_ly(mtcars, x = ~wt, y = ~mpg, color = ~vs)`. This is a major breaking change, but it is necessary to ensure that evaluation is correct in all contexts (as a result, `evaluate` argument is now deprecated as it is no longer needed). It also has the benefit of being easier to program with (i.e., writing your own custom functions that wrap `plot_ly()`) since it preserves [referential transparency](https://en.wikipedia.org/wiki/Referential_transparency). For more details, see the [lazyeval vignette](https://github.com/hadley/lazyeval/blob/master/vignettes/lazyeval.Rmd)
* The data structure used to represent plotly objects is now an htmlwidget object (instead of a data frame with a special attribute tracking visual mappings). As a result, the `last_plot()`/`as.widget()` functions have been deprecated, and [serialization/memory leak problems](https://github.com/rstudio/shiny/issues/1151) are no longer an issue. This change also implies that arbitrary data manipulation functions can no longer be intermingled inside a plot pipeline, but plotly methods for dplyr's data manipulation verbs are now provided (see `?plotly_data` for examples).
* The `group` variable mapping no longer create multiple traces, but instead defines "gaps" within a trace (fixes #418, #381, #577). Groupings should be declared via the new `group_by()` function (see `help(plotly_data)` for examples) instead of the `group` argument (which is now deprecated).
* `plot_ly()` now _initializes_ a plotly object (i.e., won't add a scatter trace by default), meaning that something like `plot_ly(x = 1:10, y = 1:10) %>% add_trace(y = 10:1)` creates one trace, instead of two. That being said, if you manually specify a trace type in `plot_ly()`, it will add a layer with that trace type (e.g. `plot_ly(x = 1:10, y = 1:10, type = "scatter") %>% add_trace(y = 10:1)` draws two scatter traces). If no trace type is provided, a sensible type is inferred from the supplied data, and automatically added (i.e., `plot_ly(x = rnorm(100))` now creates a histogram).
* The `inherit` argument is deprecated. Any arguments/attributes specified in `plot_ly()` will automatically be passed along to additional traces added via `add_trace()` (or any of it's `add_*()` siblings).
* Aesthetic scaling (e.g., `color`, `symbol`, `size`) is applied at the plot-level, instead of the trace level.
* Size is no longer automatically included in hovertext (closes #549).

NEW FEATURES & IMPROVEMENTS:
## NEW FEATURES & IMPROVEMENTS:

* Added `linetype`/`linetypes` arguments for mapping discrete variables to line types (works very much like the `symbol`/`symbols`).
* Scaling for aesthetics can be avoided via `I()` (closes #428). This is mainly useful for changing default appearance (e.g. `plot_ly(x = 1:10, y = 1:10, color = I(rainbow(10)))`).
* Scaling for aesthetics can be avoided via `I()` (closes #428). This is mainly useful for changing default appearance (e.g. `plot_ly(x = 1:10, y = 1:10, color = I("red"))`).
* Symbols and linetypes now recognize `pch` and `lty` values (e.g. `plot_ly(x = 1:25, y = 1:25, symbol = I(0:24))`)
* A new `alpha` argument controls the alpha transparency of `color` (e.g. `plot_ly(x = 1:10, y = 1:10, color = I("red"), alpha = 0.1)`).
* Added a `sizes` argument for controlling the range of marker size scaling.
Expand All @@ -24,7 +35,7 @@ NEW FEATURES & IMPROVEMENTS:
* New `plotly_json()` function for inspecting the data sent to plotly.js (as an R list or JSON).
* `layout()` is now a generic function and uses method dispatch to avoid conflicts with `graphics:layout()` (fixes #464).

OTHER CHANGES:
## OTHER CHANGES:

* Upgraded to plotly.js v1.14.1 -- https://github.com/plotly/plotly.js/releases/tag/v1.14.1

Expand Down
12 changes: 12 additions & 0 deletions R/deprecated.R
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,15 @@ as.widget <- function(x, ...) {

# for legacy reasons
toWidget <- as.widget

#' Retrive and create the last plotly (or ggplot).
#'
#' This function was deprecated in version 4.0.
#'
#' @param data (optional) a data frame with a class of plotly (and a plotly_hash attribute).
#' @export

last_plot <- function(data = NULL) {
.Deprecated("plot_ly")
data
}
10 changes: 8 additions & 2 deletions R/plotly_build.R
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ plotly_build.plotly <- function(p) {
# Fortunately, variable mappings don't make much sense with one observation,
# and that is the whole point of "recovering" the built data here, so we just ignore
# cases with one row
isVar <- attrLengths > 1 & attrLengths == nobs & !vapply(trace, is.matrix, logical(1))
isVar <- (attrLengths > 1 & attrLengths == nobs) &
!vapply(trace, is.matrix, logical(1)) &
!vapply(trace, is.bare.list, logical(1))
builtData <- data.frame(trace[isVar], stringsAsFactors = FALSE)

if (NROW(builtData) > 0) {
Expand Down Expand Up @@ -181,7 +183,11 @@ plotly_build.plotly <- function(p) {
retrace.first = inherits(x, "plotly_polygon")
)
for (i in x$.plotlyVariableMapping) {
x[[i]] <- structure(uniq(d[[i]]), class = oldClass(x[[i]]))
# try to reduce the amount of data we have to send for non-positional scales
x[[i]] <- structure(
if (i %in% npscales()) uniq(d[[i]]) else d[[i]],
class = oldClass(x[[i]])
)
}
x
})
Expand Down
Binary file modified R/sysdata.rda
Binary file not shown.
4 changes: 4 additions & 0 deletions R/utils.R
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ is.colorbar <- function(tr) {
inherits(tr, "plotly_colorbar")
}

is.bare.list <- function(x) {
is.list(x) && !is.data.frame(x)
}

"%||%" <- function(x, y) {
if (length(x) > 0 || is_blank(x)) x else y
}
Expand Down
34 changes: 17 additions & 17 deletions inst/htmlwidgets/lib/plotlyjs/plotly-latest.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion inst/htmlwidgets/plotly.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dependencies:
- name: plotlyjs
version: 1.14.1
version: 1.14.2
src: "htmlwidgets/lib/plotlyjs"
script: plotly-latest.min.js
stylesheet: plotly-htmlwidgets.css
15 changes: 15 additions & 0 deletions man/last_plot.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions tests/testthat.R
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ skip_on_pull_request <- function() {
# object (aka the data behind the plot).
save_outputs <- function(gg, name) {
print(paste("Running test:", name))
p <- plotly_build(gg)$x
p <- plotly_build(gg)$x[c("data", "layout")]
has_diff <- if (report_diffs) {
# save a hash of the R object
plot_hash <- digest::digest(p)
Expand All @@ -84,7 +84,8 @@ save_outputs <- function(gg, name) {
!isTRUE(plot_hash == test_info$hash)
} else FALSE
if (has_diff || build_table) {
pm <- RSeval(conn, "tryCatch(plotly::plotly_build(gg)$x, error = function(e) 'plotly build error')")
RSassign(conn, gg)
pm <- RSeval(conn, "tryCatch(plotly::plotly_build(gg)$x[c('data', 'layout')], error = function(e) e$message)")
if (build_table) {
# save pngs of ggplot
filename <- paste0(gsub("\\s+", "-", name), ".png")
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-plotly-color.R
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ test_that("Custom RColorBrewer pallette works for numeric variable", {
})

test_that("axis titles get attached to scene object for 3D plots", {
p <- plot_ly(iris, x = ~Petal.Length, y = ~Petal.Width, z = ~Sepal.Width,
type = "scatter3d", mode = "markers")
p <- plot_ly(iris, x = ~Petal.Length, y = ~Petal.Width, z = ~Sepal.Width)
l <- expect_traces(p, 1, "scatterplot-scatter3d-axes")
expect_identical(l$data[[1]]$type, "scatter3d")
scene <- l$layout$scene
expect_identical(scene$xaxis$title, "Petal.Length")
expect_identical(scene$yaxis$title, "Petal.Width")
Expand Down
4 changes: 2 additions & 2 deletions tests/testthat/test-plotly-linetype.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ test_that("Mapping a variable to linetype works", {

test_that("Can set the linetype range.", {
p <- plot_ly(tx, x = ~date, y = ~median, linetype = ~city, linetypes = 5:1)
l <- expect_traces(p, 5, "linetype")
l <- expect_traces(p, 5, "linetype2")
lines <- lapply(l$data, "[[", "line")
dashes <- unlist(lapply(lines, "[[", "dash"))
expect_equal(dashes, plotly:::lty2dash(5:1))
})

test_that("Can avoid scaling", {
p <- plot_ly(tx, x = ~date, y = ~median, linetype = I(3))
l <- expect_traces(p, 1, "linetype")
l <- expect_traces(p, 1, "linetype3")
lines <- lapply(l$data, "[[", "line")
dashes <- unlist(lapply(lines, "[[", "dash"))
expect_equal(dashes, plotly:::lty2dash(3))
Expand Down
7 changes: 7 additions & 0 deletions tests/testthat/test-plotly.R
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ expect_same_data <- function(p1, p2) {
expect_identical(d1, d2)
}

test_that("vector values with repeated values are returned verbatim", {
p <- plot_ly(x = c(1, 2), y = c(1, 1))
l <- plotly_build(p)$x
expect_identical(l$data[[1]]$x, c(1, 2))
expect_identical(l$data[[1]]$y, c(1, 1))
})

test_that("plot_ly defaults to scatterplot", {
p1 <- plot_ly(mtcars, x = ~wt, y = ~mpg)
p2 <- plot_ly(mtcars, x = ~wt, y = ~mpg) %>% add_markers()
Expand Down
55 changes: 51 additions & 4 deletions vignettes/intro.Rmd
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
---
title: "An overview of plotly's R API"
title: "An intro to `plot_ly()`"
author: "Carson Sievert"
date: "`r Sys.Date()`"
output:
rmarkdown::html_vignette:
self_contained: false
rmarkdown::html_vignette
vignette: >
%\VignetteEngine{knitr::rmarkdown}
%\VignetteIndexEntry{Plotly DSL}
%\VignetteIndexEntry{Plotly Intro}
---

```{r, echo = FALSE}
Expand All @@ -18,6 +18,53 @@ knitr::opts_chunk$set(
)
```



This vignette outlines the philosophy behind `plot_ly()` through a series of examples (click on the static images to see the interactive version). In a nutshell, `plot_ly()` aims to:

1. Provide sensible defaults/messages/warnings based on the information supplied, but still allows for full customization through [plotly.js](https://github.com/plotly/plotly.js)' (the open source JavaScript graphing library which powers plotly) [figure reference](https://plot.ly/r/reference/).
2. Leverage useful concepts from the grammar of graphics (without requiring it to be used).

## Smart defaults, messages, warnings, errors

If no visualization type is specified, `plot_ly()` infers a sensible type based on the information provided. In this case, a numeric matrix (named `volcano`) is mapped to the `z` attribute, so a heatmap is a sensible default.

```{r, message = TRUE}
library(plotly)
str(volcano)
plot_ly(z = ~volcano)
```


A heatmap is not the only way to visualize a numeric matrix. Since `plot_ly()` only _initializes_ a plotly object,

we can change the default visualization type using any of the `add_*()` functions:

```{r}
add_surface(plot_ly(z = ~volcano))
```

There are a number of `add_*()` functions, for a number
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't seem like this is complete


## Functional interface

Plotly's R package has a functional interface: every function takes a plotly object as it's first input argument and returns a modified plotly object. To make code more readable, plotly re-exports the pipe operator (`%>%`) from the magrittr package. The pipe operator takes the object on the left-hand side and injects it into the first argument (by default) of the function on the right-hand side. This allows us to read code from left to right instead of inside out.

```{r, eval = FALSE}
# these two lines of code are equivalent, but the second is easier to read
plotly_POST(add_surface(plot_ly(z = ~volcano)))
plot_ly(z = ~volcano) %>% add_surface() %>% plotly_POST()
```




```{r}
plot_ly(diamonds, x = ~cut)
plot_ly(diamonds, y = ~cut)
```


To create a plotly visualization, start with `plot_ly()`.

```{r}
Expand Down
55 changes: 55 additions & 0 deletions vignettes/overview.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
title: "plotly overview"
author: "Carson Sievert"
date: "`r Sys.Date()`"
output:
rmarkdown::html_vignette:
self_contained: false
vignette: >
%\VignetteEngine{knitr::rmarkdown}
%\VignetteIndexEntry{Plotly Intro}
---

```{r, echo = FALSE}
knitr::opts_chunk$set(
message = FALSE,
warning = FALSE,
fig.width = 7,
fig.height = 3
)
```

plotly is an R package for making interactive graphics via the open source JavaScript graphing library [plotly.js](https://github.com/plotly/plotly.js). It provides two main ways to create a plotly visualization: `ggplotly()` and `plot_ly()`. Both of these functions output an [htmlwidget](http://www.htmlwidgets.org/) object, which allows plots to work seamlessly and consistently across various contexts (e.g., R Markdown documents, shiny apps, inside RStudio, or any other R command prompt). For IPython/Jupyter notebook users, there is also an `embed_notebook()` function to embed plots as iframes pointing to a local HTML file. For [plot.ly](https://plot.ly/) subscribers, there is a `plotly_POST()` function for sending local graphs to your account, and a `get_figure()` function for downloading publicly hosted plot.ly figure(s).

## Translate ggplot2 to plotly with `ggplotly()`

The `ggplotly()` function translates [ggplot2](https://cran.r-project.org/web/packages/ggplot2/index.html) graphics to a plotly equivalent, for example:

```{r}
library(plotly)
p <- ggplot(txhousing, aes(x = date, y = median, group = city)) +
geom_line(alpha = 0.3) +
geom_line(data = subset(txhousing, city == "Houston"), color = "red")
ggplotly(p)
```

If you know ggplot2, `ggplotly()` is great since you can add some interactivity (specifically, idenfication + zoom & pan) to your plots for free. Also,

The `ggplotly()` function tries its best to replicate what you see _exactly_ in the static ggplot2 graph.

The output of a `ggplotly()` function is a plotly object.

## The `plot_ly()` interface

The `plot_ly()` function draws inspiration from ggplot2's implementation of the grammar of graphics, but provides a more flexible and direct interface to [plotly.js](https://github.com/plotly/plotly.js). The interface is also functional, and designed to work with dplyr, so visualization can be described as a sequence of data manipulations and visual components via the pipe operator (`%>%`) from the magrittr package.

```{r}
txhousing %>%
group_by(city) %>%
plot_ly(x = ~date, y = ~median) %>%
add_lines(alpha = 0.3, color = I("black"), name = "Texan Cities") %>%
filter(city == "Houston") %>%
add_lines(color = I("red"), name = "Houston")
```

TODO: list resources