From 212d2a8d7ff0b9d45aa108cfbd4d649fcbcb71bb Mon Sep 17 00:00:00 2001 From: pvictor Date: Mon, 9 Sep 2024 14:13:47 +0200 Subject: [PATCH] added v_waterfall() --- NAMESPACE | 1 + R/layers.R | 64 +++++++++++++++++++++++++++++++++++++++ R/scales.R | 2 ++ examples/v_waterfall.R | 31 +++++++++++++++++++ man/v_waterfall.Rd | 69 ++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 167 insertions(+) create mode 100644 examples/v_waterfall.R create mode 100644 man/v_waterfall.Rd diff --git a/NAMESPACE b/NAMESPACE index cc705c8..ddcbc79 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -63,6 +63,7 @@ export(v_theme) export(v_theme_builtin) export(v_treemap) export(v_venn) +export(v_waterfall) export(v_wordcloud) export(vars) export(vchart) diff --git a/R/layers.R b/R/layers.R index 44e2c50..be0ea42 100644 --- a/R/layers.R +++ b/R/layers.R @@ -1477,3 +1477,67 @@ v_venn <- function(vc, return(vc) } + + + +#' Create a Waterfall Chart +#' +#' @inheritParams v_bar +#' +#' @return A [vchart()] `htmlwidget` object. +#' @export +#' +#' +#' @example examples/v_waterfall.R +v_waterfall <- function(vc, + mapping = NULL, + data = NULL, + name = NULL, + ..., + serie_id = NULL, + data_id = NULL) { + stopifnot( + "\'vc\' must be a chart constructed with vchart()" = inherits(vc, "vchart") + ) + data <- get_data(vc, data) + mapping <- get_mapping(vc, mapping) + mapdata <- eval_mapping_(data, mapping) + vc$x$type <- c(vc$x$type, "waterfall") + serie_id <- serie_id %||% genSerieId() + data_id <- data_id %||% genDataId() + vc <- .vchart_specs( + vc, "data", + list( + list( + id = data_id, + values = mapdata + ) + ) + ) + serie <- list_( + type = "waterfall", + id = serie_id, + dataId = data_id, + name = name, + xField = "x", + yField = "y", + total = list( + type = "field", + tagField = "total", + valueField = "y" + ), + seriesField = if (has_name(mapping, "colour")) "colour", + ... + ) + vc <- .vchart_specs(vc, "series", list(serie)) + scale_x <- attr(mapdata, "scale_x") + if (identical(scale_x, "discrete")) { + vc <- v_scale_x_discrete(vc) + } else if (identical(scale_x, "date")) { + vc <- v_scale_x_date(vc) + } else if (identical(scale_x, "continuous")) { + vc <- v_scale_x_continuous(vc) + } + vc <- v_scale_y_continuous(vc, zero = TRUE) + return(vc) +} diff --git a/R/scales.R b/R/scales.R index 2e60ff8..0dc82f3 100644 --- a/R/scales.R +++ b/R/scales.R @@ -437,6 +437,7 @@ v_scale_x_continuous <- function(vc, labels_tooltip = labels_tooltip, min = min, max = max, + zero = zero, ... ) } @@ -470,6 +471,7 @@ v_scale_y_continuous <- function(vc, labels_tooltip = labels_tooltip, min = min, max = max, + zero = zero, ... ) } diff --git a/examples/v_waterfall.R b/examples/v_waterfall.R new file mode 100644 index 0000000..cfc2767 --- /dev/null +++ b/examples/v_waterfall.R @@ -0,0 +1,31 @@ + +library(vchartr) + +balance <- data.frame( + desc = c("Starting Cash", + "Sales", "Refunds", "Payouts", "Court Losses", + "Court Wins", "Contracts", "End Cash"), + amount = c(2000, 3400, -1100, -100, -6600, 3800, 1400, 2800) +) + +vchart(balance) %>% + v_waterfall(aes(x = desc, y = amount)) + + +# With total values and formatting +data.frame( + x = c("Feb.4", "Feb.11", "Feb.20", "Feb.25", "Mar.4", + "Mar.11", "Mar.19", "Mar.26", "Apr.1", "Apr.8", + "Apr.15", "Apr.22", "Apr.29", "May.6", "total"), + total = c(TRUE, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, TRUE), + y = c(45L, -5L, 2L, -2L, 2L, 2L, -2L, 1L, 1L, 1L, 2L, 1L, -2L, -1L, NA) +) %>% + vchart() %>% + v_waterfall( + aes(x = x, y = y, total = total), + stackLabel = list( + valueType = "absolute", + formatMethod = JS("text => text + '%'") + ) + ) %>% + v_specs_legend(visible = TRUE) diff --git a/man/v_waterfall.Rd b/man/v_waterfall.Rd new file mode 100644 index 0000000..8bd0e4b --- /dev/null +++ b/man/v_waterfall.Rd @@ -0,0 +1,69 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/layers.R +\name{v_waterfall} +\alias{v_waterfall} +\title{Create a Waterfall Chart} +\usage{ +v_waterfall( + vc, + mapping = NULL, + data = NULL, + name = NULL, + ..., + serie_id = NULL, + data_id = NULL +) +} +\arguments{ +\item{vc}{A chart initialized with \code{\link[=vchart]{vchart()}}.} + +\item{mapping}{Default list of aesthetic mappings to use for chart.} + +\item{data}{Default dataset to use for chart. If not already +a \code{data.frame}, it will be coerced to with \code{as.data.frame}.} + +\item{name}{Name for the serie, only used for single serie (no \code{color}/\code{fill} aesthetic supplied).} + +\item{...}{Additional parameters for the serie.} + +\item{data_id, serie_id}{ID for the data/serie, can be used to further customize the chart with \code{\link[=v_specs]{v_specs()}}.} +} +\value{ +A \code{\link[=vchart]{vchart()}} \code{htmlwidget} object. +} +\description{ +Create a Waterfall Chart +} +\examples{ + +library(vchartr) + +balance <- data.frame( + desc = c("Starting Cash", + "Sales", "Refunds", "Payouts", "Court Losses", + "Court Wins", "Contracts", "End Cash"), + amount = c(2000, 3400, -1100, -100, -6600, 3800, 1400, 2800) +) + +vchart(balance) \%>\% + v_waterfall(aes(x = desc, y = amount)) + + +# With total values and formatting +data.frame( + x = c("Feb.4", "Feb.11", "Feb.20", "Feb.25", "Mar.4", + "Mar.11", "Mar.19", "Mar.26", "Apr.1", "Apr.8", + "Apr.15", "Apr.22", "Apr.29", "May.6", "total"), + total = c(TRUE, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, TRUE), + y = c(45L, -5L, 2L, -2L, 2L, 2L, -2L, 1L, 1L, 1L, 2L, 1L, -2L, -1L, NA) +) \%>\% + vchart() \%>\% + v_waterfall( + aes(x = x, y = y, total = total), + stackLabel = list( + valueType = "absolute", + formatMethod = JS("text => text + '\%'") + ) + ) \%>\% + v_specs_legend(visible = TRUE) +}