Nothing
#' Obtain data associated with a plotly graph
#'
#' `plotly_data()` returns data associated with
#' a plotly visualization (if there are multiple data frames, by default,
#' it returns the most recent one).
#'
#' @param p a plotly visualization.
#' @param id a character string or number referencing an "attribute layer".
#'
#' @param .data a plotly visualization.
#' @param x a plotly visualization.
#' @param ... arguments passed onto the relevant method.
#'
#' @name plotly_data
#' @export
#' @examplesIf interactive() || !identical(.Platform$OS.type, "windows")
#'
#' # use group_by() to define groups of visual markings
#' p <- txhousing %>%
#' group_by(city) %>%
#' plot_ly(x = ~date, y = ~sales)
#' p
#'
#' # plotly objects preserve data groupings
#' groups(p)
#' plotly_data(p)
#'
#' # dplyr verbs operate on plotly objects as if they were data frames
#' p <- economics %>%
#' plot_ly(x = ~date, y = ~unemploy / pop) %>%
#' add_lines() %>%
#' mutate(rate = unemploy / pop) %>%
#' filter(rate == max(rate))
#' plotly_data(p)
#' add_markers(p)
#' layout(p, annotations = list(x = ~date, y = ~rate, text = "peak"))
#'
#' # use group_by() + do() + subplot() for trellis displays
#' d <- group_by(mpg, drv)
#' plots <- do(d, p = plot_ly(., x = ~cty, name = ~drv))
#' subplot(plots[["p"]], nrows = 3, shareX = TRUE)
#'
#' # arrange displays by their mean
#' means <- summarise(d, mn = mean(cty, na.rm = TRUE))
#' means %>%
#' dplyr::left_join(plots) %>%
#' arrange(mn) %>%
#' subplot(nrows = NROW(.), shareX = TRUE)
#'
#' # more dplyr verbs applied to plotly objects
#' p <- mtcars %>%
#' plot_ly(x = ~wt, y = ~mpg, name = "scatter trace") %>%
#' add_markers()
#' p %>% slice(1) %>% plotly_data()
#' p %>% slice(1) %>% add_markers(name = "first observation")
#' p %>% filter(cyl == 4) %>% plotly_data()
#' p %>% filter(cyl == 4) %>% add_markers(name = "four cylinders")
#'
#'
plotly_data <- function(p, id = p$x$cur_data) {
if (!is.plotly(p)) {
stop("`plotly_data()` expects a plotly object as it's first argument.", call. = FALSE)
}
f <- p$x$visdat[[id]]
# if data has been specified, f should be a closure that, when called,
# returns data
if (is.null(f)) return(f)
if (!is.function(f)) stop("Expected a closure", call. = FALSE)
dat <- f()
if (crosstalk::is.SharedData(dat)) {
key <- dat$key()
set <- dat$groupName()
dat <- dat$origData()
dat[[crosstalk_key()]] <- key
# not allowed for list-columns!
#dat <- dplyr::group_by_(dat, crosstalk_key(), add = TRUE)
dat <- structure(dat, set = set)
}
prefix_class(dat, "plotly_data")
}
#' @export
print.plotly_data <- function(x, ...) {
print(remove_class(tibble::as_tibble(x, ...), "plotly_data"))
x
}
#' Highlight/query data based on primary key
#'
#' This function simply creates an object of class [crosstalk::SharedData].
#' The reason it exists is to make it easier to teach others how to leverage
#' its functionality in plotly. It also makes it more discoverable if one
#' is already aware of [highlight].
#'
#' @param x a plotly visualization or a `data.frame`.
#' @param ... arguments passed to `crosstalk::SharedData$new()`
#' @export
#' @author Carson Sievert
#' @return An object of class [crosstalk::SharedData]
#' @seealso [highlight]
highlight_key <- function(x, ...) {
UseMethod("highlight_key")
}
#' @export
highlight_key.plotly <- function(x, ...) {
d <- plotly_data(x)
add_data(x, crosstalk::SharedData$new(d, ...))
}
#' @export
highlight_key.default <- function(x, ...) {
crosstalk::SharedData$new(x, ...)
}
# ---------------------------------------------------------------------------
# dplyr methods
# ---------------------------------------------------------------------------
#' @rdname plotly_data
groups.plotly <- function(x) {
groups(plotly_data(x))
}
#' @rdname plotly_data
ungroup.plotly <- function(x, ...) {
d <- ungroup(plotly_data(x), ...)
add_data(x, d)
}
#' @rdname plotly_data
group_by.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), group_by, ...)
if (crosstalk_key() %in% names(d)) {
d <- preserve_set(d, group_by_add, !!rlang::sym(crosstalk_key()))
}
add_data(.data, d)
}
#' @rdname plotly_data
mutate.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), mutate, ...)
add_data(.data, d)
}
#' @rdname plotly_data
do.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), do, ...)
add_data(.data, d)
}
#' @rdname plotly_data
summarise.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), summarise, ...)
add_data(.data, d)
}
#' @rdname plotly_data
arrange.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), arrange, ...)
add_data(.data, d)
}
#' @rdname plotly_data
select.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), select, ...)
add_data(.data, d)
}
#' @rdname plotly_data
filter.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), filter, ...)
add_data(.data, d)
}
#' @rdname plotly_data
distinct.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), distinct, ...)
add_data(.data, d)
}
#' @rdname plotly_data
slice.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), slice, ...)
add_data(.data, d)
}
#' @rdname plotly_data
rename.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), rename, ...)
add_data(.data, d)
}
#' @rdname plotly_data
transmute.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), transmute, ...)
add_data(.data, d)
}
# Apply a dplyr generic to a dataset while preserving the crosstalk 'set' attribute
preserve_set <- function(.data, func, ...) {
structure(func(.data, ...), set = attr(.data, "set"))
}
# ------------------------------------------------------------
# Deprecated dplyr non-nse generics
# ------------------------------------------------------------
#' @rdname plotly_data
group_by_.plotly <- function(.data, ...) {
d <- group_by_(plotly_data(.data), ...)
# add crosstalk key as a group (to enable examples like demos/highlight-pipeline.R)
if (crosstalk_key() %in% names(d)) {
d <- group_by_add(d, !!rlang::sym(crosstalk_key()), add = TRUE)
}
add_data(.data, d)
}
#' @rdname plotly_data
mutate_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), mutate_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
do_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), do_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
summarise_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), summarise_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
arrange_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), arrange_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
select_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), select_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
filter_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), filter_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
distinct_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), distinct_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
slice_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), slice_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
rename_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), rename_, ...)
add_data(.data, d)
}
#' @rdname plotly_data
transmute_.plotly <- function(.data, ...) {
d <- preserve_set(plotly_data(.data), transmute_, ...)
add_data(.data, d)
}
# ---------------------------------------------------------------------------
# tidyr methods
# waiting on https://github.com/tidyverse/tidyr/pull/229
# ---------------------------------------------------------------------------
# #' @rdname plotly_data
# #' @export
# gather_.plotly <- function(data, key_col, value_col, gather_cols, na.rm = FALSE,
# convert = FALSE, factor_key = FALSE) {
# d <- plotly_data(data)
# set <- attr(d, "set")
# d <- tidyr::gather_(
# d, key_col = key_col, value_col = value_col, gather_cols = gather_cols,
# na.rm = na.rm, convert = convert, factor_key = factor_key
# )
# add_data(data, structure(d, set = set))
# }
#
# #' @importFrom dplyr select_vars
# #' @rdname plotly_data
# #' @export
# gather_vars.plotly <- function(data, key_col, value_col, ...) {
# d <- plotly_data(data)
# if (n_dots(...) == 0) {
# setdiff(colnames(d), c(key_col, value_col))
# } else {
# unname(dplyr::select_vars(colnames(d), ...))
# }
# }
#
# n_dots <- function(...) nargs()
# ---------------------------------------------------------------------------
# miscellanous methods
# ---------------------------------------------------------------------------
# Avoid errors when passing a shared data to ggplot2
# qplot(data = crosstalk::SharedData$new(mtcars), mpg, wt)
#' @export
fortify.SharedData <- function(model, data, ...) {
key <- model$key()
set <- model$groupName()
data <- model$origData()
# need a consistent name so we know how to access it ggplotly()
data[[crosstalk_key()]] <- key
structure(data, set = set)
}
# yes, you can feed a plotly object into ggplot %^)
#' @export
ggplot.plotly <- function(data, mapping = aes(), ...,
environment = parent.frame()) {
ggplot(plotly_data(data), mapping = mapping, ..., environment = environment)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.