Nothing
#' Create a highchart object from a particular data type
#'
#' \code{hchart} uses `highchart` to draw a particular plot for an
#' object of a particular class in a single command. This defines the S3
#' generic that other classes and packages can extend.
#'
#' Run \code{methods(hchart)} to see what objects are supported.
#'
#' @param object A R object.
#' @param ... Additional arguments for the data series
#' (\url{https://api.highcharts.com/highcharts/series}).
#'
#' @export
hchart <- function(object, ...) {
UseMethod("hchart")
}
#' @export
hchart.default <- function(object, ...) {
stop("Objects of class/type ", paste(class(object), collapse = "/"),
" are not supported by hchart (yet).",
call. = FALSE
)
}
#' @export
hchart.list <- function(object, ...) {
if (getOption("highcharter.verbose")) {
message("hchart.list")
}
highchart() %>%
hc_add_series(data = object, ...)
}
#' @export
hchart.data.frame <- function(object, type = NULL, mapping = hcaes(), ...) {
if (getOption("highcharter.verbose")) {
message("hchart.data.frame")
}
object <- as.data.frame(object)
data <- mutate_mapping(object, mapping)
series <- data_to_series(data, mapping, type = type, ...)
opts <- data_to_options(data, type)
hc <- highchart()
if (opts$add_colorAxis) {
hc <- hc_colorAxis(hc, auxpar = NULL)
}
hc <- hc %>%
hc_add_series_list(series) %>%
hc_xAxis(
type = opts$xAxis_type,
title = list(text = as.character(mapping$x)),
categories = opts$xAxis_categories
) %>%
hc_yAxis(
type = opts$yAxis_type,
title = list(text = as.character(mapping$y)),
categories = opts$yAxis_categories
) %>%
hc_plotOptions(
series = list(
showInLegend = opts$series_plotOptions_showInLegend
),
scatter = list(marker = list(symbol = "circle"))
)
hc
}
#' @export
hchart.tibble <- hchart.data.frame
#' @importFrom graphics hist
#' @export
hchart.numeric <- function(object, breaks = "FD", ...) {
h <- hist(object, plot = FALSE, breaks = breaks)
hchart.histogram(h, ...)
}
#' @export
hchart.histogram <- function(object, ...) {
d <- diff(object$breaks)[1]
df <- tibble(
x = object$mids,
y = object$counts,
name = sprintf("(%s, %s]", object$mids - d / 2, object$mids + d / 2)
)
highchart() %>%
hc_chart(zoomType = "x") %>%
hc_tooltip(formatter = JS("function() { return this.point.name + '<br/>' + this.y; }")) %>%
hc_add_series(
data = list_parse(df),
type = "column",
pointRange = d,
groupPadding = 0,
pointPadding = 0,
borderWidth = 0,
...
)
}
#' @export
hchart.character <- function(object, type = "column", ...) {
highchart() %>%
hc_xAxis(type = "category") %>%
hc_add_series(data = object, type = type, ...)
}
#' @export
hchart.factor <- hchart.character
#' @export
hchart.ts <- function(object, ...) {
highchart() %>%
hc_xAxis(type = "datetime") %>%
hc_add_series(data = object, ...)
}
#' @export
hchart.xts <- function(object, ...) {
highchart(type = "stock") %>%
hc_add_series(data = object, ...)
}
#' @export
hchart.forecast <- function(object, addOriginal = TRUE, addLevels = TRUE, ...) {
highchart() %>%
hc_xAxis(type = "datetime") %>%
hc_add_series(
data = object, addOriginal = addOriginal,
addLevels = addLevels, ...
)
}
#' @export
hchart.mforecast <- function(object, separate = TRUE, fillOpacity = 0.3, ...) {
ntss <- ncol(object$x)
lvls <- object$level
tmf <- datetime_to_timestamp(zoo::as.Date(time(object$mean[[1]])))
nms <- attr(object$x, "dimnames")[[2]]
hc <- hchart.mts2(object$x) %>%
hc_plotOptions(
series = list(
marker = list(enabled = FALSE)
)
)
# means
hc <- hc %>% hc_add_series(data = NULL, id = "forecasts", name = "forecasts")
for (i in seq(ntss)) {
nm <- nms[i]
hc <- hc %>%
hc_add_series(object$mean[[nm]],
name = paste("forecast", nm),
yAxis = i - 1, linkedTo = "forecasts", ...
)
}
# levels
for (lvl in seq_along(lvls)) {
idlvl <- paste0("level", lvls[lvl])
nmlvl <- paste("level", lvls[lvl])
hc <- hc %>% hc_add_series(data = NULL, id = idlvl, name = nmlvl, ...)
for (i in seq(ntss)) {
nm <- nms[i]
dfbands <- tibble(
t = tmf,
u = as.vector(object$upper[[i]][, lvl]),
l = as.vector(object$lower[[i]][, lvl])
)
hc <- hc %>%
hc_add_series(
data = list_parse2(dfbands),
name = paste(nmlvl, nm),
linkedTo = idlvl,
yAxis = i - 1,
type = "arearange", fillOpacity = fillOpacity,
zIndex = 1, lineWidth = 0, ...
)
}
}
if (!separate) {
hc$x$hc_opts$yAxis <- NULL
hc$x$hc_opts$series <- map(hc$x$hc_opts$series, function(x) {
x$yAxis <- NULL
x
})
}
hc
}
#' @importFrom stats qnorm
#' @export
hchart.acf <- function(object, ...) {
ytitle <- switch(object$type,
partial = "Partial ACF",
covariance = "ACF (cov)",
correlation = "ACF"
)
sv <- qnorm(1 - 0.05 / 2) / sqrt(object$n.used)
ds <- tibble(
x = seq(object$lag[, , ]),
y = object$acf[, , ]
)
hc <- highchart() %>%
hc_add_series(
data = list_parse(ds),
type = "column",
groupPadding = 1,
name = ytitle
)
if (object$type != "covariance") {
hc <- hc %>%
hc_yAxis(
plotLines = list(
list(width = 1, value = sv, color = "gray"),
list(width = 1, value = -sv, color = "gray")
)
)
}
hc
}
#' @export
hchart.mts <- function(object, ..., separate = TRUE,
heights = rep(1, ncol(object))) {
if (separate) {
hc <- hchart.mts2(object, heights = heights, ...)
} else {
hc <- hchart.mts1(object, ...)
}
hc
}
hchart.mts1 <- function(object, ...) {
hc <- highchart() %>%
hc_xAxis(type = "datetime")
for (i in seq(dim(object)[2])) {
nm <- attr(object, "dimnames")[[2]][i]
if ("ts" %in% class(object[, i])) {
hc <- hc %>% hc_add_series(object[, i], name = nm, id = nm, ...)
} else {
hc <- hc %>% hc_add_series(object[, i], name = nm, id = nm, ...)
}
}
hc
}
hchart.mts2 <- function(object, ..., heights = rep(1, ncol(object)), sep = 0.01) {
ntss <- ncol(object)
hc <- highchart() %>%
hc_xAxis(type = "datetime") %>%
hc_tooltip(shared = TRUE)
hc <- hc %>%
hc_yAxis_multiples(
create_yaxis(ntss,
heights = heights, turnopposite = TRUE,
title = list(text = NULL), offset = 0, lineWidth = 2,
showFirstLabel = FALSE, showLastLabel = FALSE, ...
)
)
namestss <- as.character(attr(object, "dimnames")[[2]])
for (col in seq(ntss)) {
nm <- namestss[col]
hc <- hc %>% hc_add_series(object[, col], yAxis = col - 1, name = nm, id = nm, ...)
}
hc
}
#' @export
hchart.stl <- function(object, ..., heights = c(2, 1, 1, 1), sep = 0.01) {
tss <- object$time.series
ncomp <- ncol(tss)
data <- drop(tss %*% rep(1, ncomp))
tss <- cbind(data = data, tss)
attr(tss, "dimnames")[[2]] <- gsub("tss\\.", "", attr(tss, "dimnames")[[2]])
hchart.mts2(tss)
}
#' @export
hchart.ets <- function(object, ...) {
names <- c(y = "observed", l = "level", b = "slope", s1 = "season")
data <- cbind(object$x, object$states[, colnames(object$states) %in% names(names)])
cn <- c("y", c(colnames(object$states)))
colnames(data) <- cn <- names[stats::na.exclude(match(cn, names(names)))]
hc <- hchart.mts2(data)
hc <- hc_title(hc, text = paste("Decomposition by", object$method, "method"))
hc
}
#' @importFrom tidyr gather
#' @importFrom dplyr count_ left_join select
#' @importFrom rlang .data
#' @export
hchart.matrix <- function(object, label = FALSE, showInLegend = FALSE, ...) {
if (getOption("highcharter.verbose")) {
message("hchart.maxtrix")
}
stopifnot(is.numeric(object))
df <- as.data.frame(object)
ismatrix <- is.null(colnames(object)) & is.null(rownames(object))
pos <- ifelse(ismatrix, 0, 1)
xnm <- if (is.null(colnames(object))) seq_len(ncol(object)) else colnames(object)
xnm <- as.character(xnm)
xid <- seq(length(xnm)) - pos
ynm <- if (is.null(rownames(object))) seq_len(nrow(object)) else rownames(object)
ynm <- as.character(ynm)
yid <- seq(length(ynm)) - pos
ds <- as.data.frame(df) %>%
tibble::as_tibble() %>%
bind_cols(tibble(ynm), .) %>%
gather("key", "value", -ynm) %>%
rename(xnm = .data$key) %>%
mutate(
xnm = as.character(.data$xnm),
ynm = as.character(.data$ynm)
)
ds$xnm <- if (is.null(colnames(object))) str_replace(ds$xnm, "V", "") else ds$xnm
ds <- ds %>%
left_join(tibble(xnm, xid), by = "xnm") %>%
left_join(tibble(ynm, yid), by = "ynm") %>%
mutate(name = paste(.data$xnm, .data$ynm, sep = " ~ ")) %>%
select(x = .data$xid, y = .data$yid, .data$value, .data$name)
fntltp <- JS("function(){
return this.point.name + ': ' +
Highcharts.numberFormat(this.point.value, 2)
}")
hc <- highchart() %>%
hc_add_series(data = list_parse(ds), type = "heatmap") %>%
hc_plotOptions(
series = list(
showInLegend = showInLegend,
boderWidth = 0,
dataLabels = list(enabled = label)
)
) %>%
hc_tooltip(formatter = fntltp) %>%
hc_legend(enabled = TRUE) %>%
hc_colorAxis(auxarg = TRUE)
if (ismatrix) {
hc <- hc %>%
hc_xAxis(visible = FALSE) %>%
hc_yAxis(visible = FALSE, reversed = TRUE)
} else {
hc <- hc %>%
hc_xAxis(categories = xnm, title = list(text = ""), opposite = TRUE) %>%
hc_yAxis(categories = ynm, title = list(text = ""), reversed = TRUE)
}
# correlogram
if (-1 <= min(object) & min(object) < 0 & max(object) <= 1) {
hc <- hc_colorAxis(hc,
stops = color_stops(3, c("#FF5733", "#F8F5F5", "#2E86C1")),
min = -1, max = 1
)
} else {
hc <- hc_colorAxis(hc, nullpar = NULL)
}
hc
}
#' @importFrom tidyr gather
#' @importFrom dplyr count_ left_join select_
#' @export
hchart.dist <- function(object, ...) {
hchart.matrix(as.matrix(object))
}
#' @importFrom igraph vertex_attr edge_attr get.edgelist layout_nicely
#' @importFrom stats setNames
#' @importFrom rlang .data
#' @export
hchart.igraph <- function(object, ..., layout = layout_nicely, digits = 2) {
# data
dfv <- layout(object) %>%
round(digits) %>%
data.frame() %>%
tibble::as_tibble() %>%
setNames(c("x", "y"))
dfvex <- object %>%
vertex_attr() %>%
data.frame(stringsAsFactors = FALSE) %>%
tibble::as_tibble()
if (nrow(dfvex) > 0) {
dfv <- tibble::as_tibble(cbind(dfv, dfvex))
}
if (is.null(dfv[["name"]])) {
dfv <- dfv %>% mutate(name = seq(nrow(dfv)))
}
names(dfv) <- str_replace_all(names(dfv), "\\.", "_")
dfe <- object %>%
get.edgelist() %>%
data.frame(stringsAsFactors = FALSE) %>%
tibble::as_tibble() %>%
setNames(c("from", "to")) %>%
left_join(dfv %>%
select(.data$name, .data$x, .data$y) %>%
setNames(c("from", "xf", "yf")), by = "from") %>%
left_join(dfv %>%
select(.data$name, .data$x, .data$y) %>%
setNames(c("to", "xt", "yt")), by = "to") %>%
mutate(linkedTo = "e")
dfex <- object %>%
edge_attr() %>%
data.frame(stringsAsFactors = FALSE) %>%
tibble::as_tibble()
if (nrow(dfex) > 0) {
dfe <- tibble::as_tibble(cbind(dfe, dfex))
}
# Checking opts
type <- "scatter"
if ("size" %in% names(dfv)) {
dfv <- dfv %>% rename(z = .data$size)
type <- "bubble"
}
if ("group" %in% names(dfv)) {
dfv <- dfv %>% rename(groupvar = .data$group)
}
if ("width" %in% names(dfe)) {
dfe <- dfe %>% rename(lineWidth = .data$width)
}
if (!"color" %in% names(dfe)) {
dfe <- dfe %>% mutate("color" = hex_to_rgba("#d3d3d3", 0.5))
}
dse <- list_parse(dfe) %>%
map(function(x) {
x$data <- list(
list(x = x$xf, y = x$yf),
list(x = x$xt, y = x$yt)
)
x[c("xf", "yf", "xt", "yt")] <- NULL
x
})
vattrs <- setdiff(names(dfv), c("x", "y", "z", "color", "label", "name"))
tltip_fmt <- tooltip_table(
str_to_title(str_replace_all(vattrs, "_", " ")),
sprintf("{point.%s}", vattrs)
)
hc <- highchart() %>%
hc_chart(zoomType = "xy", type = "line") %>%
hc_tooltip(
useHTML = TRUE
) %>%
hc_plotOptions(
line = list(enableMouseTracking = FALSE),
bubble = list(
marker = list(fillOpacity = 0.65),
minSize = 5, maxSize = 20
)
) %>%
hc_add_theme(
hc_theme_null(legend = list(enabled = TRUE))
)
hc <- hc %>%
hc_add_series(
data = list_parse(dfv),
type = type, name = "nodes", zIndex = 3,
tooltip = list(
headerFormat = as.character(tags$small("{point.key}")),
pointFormat = tltip_fmt
), ...
)
if ("label" %in% names(dfv)) {
hc <- hc %>%
hc_add_series(
data = list_parse(dfv %>% select(.data$x, .data$y, .data$label)),
type = "scatter", name = "labels", zIndex = 4,
marker = list(radius = 0), enableMouseTracking = FALSE,
dataLabels = list(enabled = TRUE, format = "{point.label}")
)
}
hc <- hc %>%
hc_add_series(data = NULL, name = "edges", id = "e") %>%
hc_add_series_list(dse)
hc
}
#' Plot survival curves using Highcharts
#'
#' @param object A survfit object as returned from the \code{survfit} function
#' @param ... Extra parameters to pass to \code{hc_add_series} function
#' @param fun Name of function or function used to transform the survival curve:
#' \code{log} will put y axis on log scale, \code{event} plots cumulative events
#' (f(y) = 1-y), \code{cumhaz} plots the cumulative hazard function (f(y) =
#' -log(y)), and \code{cloglog} creates a complimentary log-log survival plot
#' (f(y) = log(-log(y)) along with log scale for the x-axis.
#' @param markTimes Label curves marked at each censoring time? TRUE by default
#' @param symbol Symbol to use as marker (plus sign by default)
#' @param markerColor Color of the marker ("black" by default); use NULL to use
#' the respective color of each series
#' @param ranges Plot interval ranges? FALSE by default
#' @param rangesOpacity Opacity of the interval ranges (0.3 by default)
#'
#' @return Highcharts object to plot survival curves
#'
#' @examples
#'
#' # Plot Kaplan-Meier curves
#' require("survival")
#' leukemia.surv <- survfit(Surv(time, status) ~ x, data = aml)
#' hchart(leukemia.surv)
#'
#' # Plot the cumulative hazard function
#' lsurv2 <- survfit(Surv(time, status) ~ x, aml, type = "fleming")
#' hchart(lsurv2, fun = "cumhaz")
#'
#' # Plot the fit of a Cox proportional hazards regression model
#' fit <- coxph(Surv(futime, fustat) ~ age, data = ovarian)
#' ovarian.surv <- survfit(fit, newdata = data.frame(age = 60))
#' hchart(ovarian.surv, ranges = TRUE)
#' @export
hchart.survfit <- function(object, ..., fun = NULL, markTimes = TRUE,
symbol = "plus", markerColor = "black",
ranges = FALSE, rangesOpacity = 0.3) {
group <- NULL
# Check if there are groups
if (is.null(object$strata)) {
strata <- c("Series 1" = length(object$time))
} else {
strata <- object$strata
}
# Modify data according to functions (adapted from survival:::plot.survfit)
if (is.character(fun)) {
tfun <- switch(fun,
log = function(x) x,
event = function(x) 1 - x,
cumhaz = function(x) -log(x),
cloglog = function(x) log(-log(x)),
pct = function(x) x * 100,
logpct = function(x) 100 * x,
identity = function(x) x,
function(x) x
)
} else if (is.function(fun)) {
tfun <- fun
} else {
tfun <- function(x) x
}
firsty <- tfun(1)
object$surv <- tfun(object$surv)
if (ranges && !is.null(object$upper)) {
object$upper <- tfun(object$upper)
object$lower <- tfun(object$lower)
}
# Prepare data
data <- data.frame(
x = object$time, y = object$surv,
up = object$upper, low = object$lower,
group = rep(names(strata), strata),
stringsAsFactors = FALSE
)
# Data markers
marker <- list(list(fillColor = markerColor, symbol = symbol, enabled = TRUE))
if (markTimes) {
mark <- object$n.censor == 1
} else {
mark <- FALSE
}
# Adjust Y axis range
yValues <- object$surv
ymin <- ifelse(min(yValues) >= 0, 0, min(yValues))
ymax <- ifelse(max(yValues) <= 1, 1, max(yValues))
hc <- highchart() %>%
hc_tooltip(shared = TRUE) %>%
hc_yAxis(min = ymin, max = ymax) %>%
hc_plotOptions(line = list(marker = list(enabled = FALSE)))
count <- 0
# Process groups by columns (CoxPH-like) or in a single column
if (!is.null(ncol(object$surv))) {
groups <- seq(ncol(object$surv))
} else {
groups <- names(strata)
}
for (name in groups) {
if (!is.null(ncol(object$surv))) {
df <- df[c("x", paste(c("y", "low", "up"), col, sep = "."))]
names(df) <- c("x", "y", "low", "up")
submark <- mark
} else {
df <- subset(data, group == name)
submark <- mark[data$group == name]
}
# Add first value if there is no value for time at 0 in the data
if (!0 %in% df$x) {
first <- list(list(x = 0, y = firsty))
} else {
first <- NULL
}
# Mark events
ls <- list_parse(df)
if (markTimes) {
ls[submark] <- lapply(ls[submark], c, marker = marker)
}
hc <- hc %>%
hc_add_series(
data = c(first, ls), step = "left", name = name, zIndex = 1,
color = JS(sprintf("Highcharts.getOptions().colors[%s]", count)),
...
)
if (ranges && !is.null(object$upper)) {
# Add interval range
range <- lapply(ls, function(i) {
setNames(i[c("x", "low", "up")], NULL)
})
hc <- hc %>%
hc_add_series(
data = range, step = "left", name = "Ranges",
type = "arearange", zIndex = 0, linkedTo = ":previous",
fillOpacity = rangesOpacity, lineWidth = 0,
color = JS(sprintf("Highcharts.getOptions().colors[%s]", count)),
...
)
}
count <- count + 1
}
hc <- hc %>%
hc_plotOptions(
series = list(
states = list(hover = list(enabled = FALSE))
)
)
return(hc)
}
#' @importFrom tibble rownames_to_column
#' @importFrom rlang .data
#' @export
hchart.density <- function(object, type = "area", ...) {
hc_add_series(highchart(), data = object, type = type, ...)
}
#' @importFrom dplyr as_tibble
hchart.pca <- function(sdev, n.obs, scores, loadings, ...,
choices = 1L:2L, scale = 1) {
stopifnot(length(choices) == 2L)
stopifnot(0 <= scale | scale <= 1)
lam <- sdev[choices]
lam <- lam * sqrt(n.obs)
if (scale != 0) {
lam <- lam^scale
} else {
lam <- 1
}
dfobs <- (scores[, choices] / lam) %>%
as.data.frame() %>%
setNames(c("x", "y")) %>%
rownames_to_column("name")
dfcomp <- loadings[, choices] * lam
mx <- max(abs(dfobs[, 2:3]))
mc <- max(abs(dfcomp))
dfcomp <- dfcomp %>%
{
. / mc * mx
} %>%
as.data.frame() %>%
setNames(c("x", "y")) %>%
rownames_to_column("name") %>%
as_tibble() %>%
group_by(.data$name) %>%
do(data = list(c(0, 0), c(.$x, .$y))) %>%
list_parse()
highchart() %>%
hc_plotOptions(
line = list(
marker = list(enabled = FALSE)
)
) %>%
hc_add_series(
data = list_parse(dfobs), name = "observations", type = "scatter",
dataLabels = list(enabled = TRUE, format = "{point.name}"), ...
) %>%
hc_add_series_list(dfcomp)
}
#' @export
hchart.princomp <- function(object, ..., choices = 1L:2L, scale = 1) {
hchart.pca(object$sdev, object$n.obs, object$scores, object$loadings,
choices = choices, scale = scale, ...
)
}
#' @importFrom dplyr as_tibble
#' @export
hchart.prcomp <- function(object, ..., choices = 1L:2L, scale = 1) {
hchart.pca(object$sdev, nrow(object$x), object$x, object$rotation,
choices = choices, scale = scale, ...
)
}
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.