library(tidyverse)
ggplot(cars) +
aes(dist, speed) +
geom_point(size = 7) +
aes(color = speed) +
scale_color_viridis_c(limits = c(0,26)) +
scale_x_continuous(limits = c(0,125)) +
scale_y_continuous(limits = c(0,25))

data_filter <- function(keep) {
structure(list(keep_specification = rlang::enquo(keep)),
class = "wipeobs")
}
ggplot_add.wipeobs <- function(object, plot, object_name) {
new_data <- dplyr::filter(plot$data,
!! object$keep_specification)
plot$data <- new_data
plot
}
last_plot() +
data_filter(keep = dist > 60)

ggplot(cars) +
aes(dist, speed) +
geom_point(size = 7) +
aes(color = speed)

data_replace <- function(data) {
structure(list(new_data_specification = data),
class = "wipedata")
}
ggplot_add.wipedata <- function(object, plot, object_name) {
plot$data <- object$new_data_specification
plot
}
last_plot() +
data_replace(data = cars %>% filter(dist > 50))

drob_funs <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-07-09/drob_funs.csv')
drob_funs %>%
ggplot() +
aes(y = funs) +
aes(y = fct_infreq(funs)) +
aes(y = fct_infreq(funs) %>% fct_rev()) +
geom_bar() ->
p; p

p +
data_replace(drob_funs %>%
group_by(funs) %>%
filter(n() > 500))

p +
data_filter(pkgs == "ggplot")

p +
data_filter(pkgs == "dplyr")

p +
data_filter(pkgs == "tidyr")

p +
data_filter(pkgs == "base")

# might not work
data_group <- function(group) {
structure(list(group_specification = rlang::enquo(group)),
class = "data_grouping")
}
ggplot_add.data_grouping <- function(object, plot, object_name) {
new_data <- dplyr::group_by(plot$data,
!! object$group_specification)
plot$data <- new_data
plot
}
p +
data_group() +
data_filter(n() > 500)

data_mutate <- function(.value, .by) {
structure(list(sum_specification = rlang::enquo(.value),
by_specification = rlang::enquo(.by)),
class = "data_summary")
}
ggplot_add.data_summary <- function(object, plot, object_name) {
new_data <- dplyr::mutate(plot$data, .value =
!! object$sum_specification,
.by = !! object$by_specification)
message("New variable named '.value' created")
plot$data <- new_data
plot
}
p +
data_mutate(.value = n(),
.by = funs) +
data_filter(.value > 500)

drob_funs %>%
ggplot() +
aes(id = funs) +
ggcirclepack::geom_circlepack() +
ggcirclepack::geom_circlepack_text() +
coord_equal() +
aes(fill = I("grey")) ->
plot_all
plot_all +
data_filter(pkgs == "ggplot")

plot_all +
data_filter(pkgs == "base")

plot_all +
data_filter(pkgs == "tidyr")

plot_all +
data_filter(pkgs == "dplyr")

plot_all +
data_filter(pkgs == "stringr")

library(tidyverse)
drob_funs <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2024/2024-07-09/drob_funs.csv')
data_mutate_filter <- function(.value, .by, keep) {
structure(list(sum_specification = rlang::enquo(.value),
by_specification = rlang::enquo(.by),
keep_specifiction = rlang::enquo(keep)),
class = "data_mutatefilter")
}
ggplot_add.data_mutatefilter <- function(object, plot, object_name) {
new_data <- dplyr::mutate(plot$data, .value =
!! object$sum_specification,
.by = !! object$by_specification) %>%
dplyr::filter(!! object$keep_specifiction)
message("New variable named '.value' created")
plot$data <- new_data
plot
}
drob_funs %>%
ggplot() +
aes(id = paste(funs, pkgs)) +
ggcirclepack::geom_circlepack() +
ggcirclepack::geom_circlepack_text(aes(label = funs)) +
coord_equal() +
aes(fill = pkgs) +
guides(fill = "none")

last_plot() +
data_mutate_filter(.value = n(),
.by = c(funs, pkgs),
keep = .value >= 200)

last_plot() +
aes(group = pkgs)

# ggcirclepack:::StatCirclepack$compute_panel
#
# StatCirclepack <- ggcirclepack:::StatCirclepack
# StatCirclepack$compute_panel <- function (data, scales, npoints = 50, fun = sum)
# {
# if (is.null(data$slice)) {
# data$slice <- TRUE
# }
# data <- data %>% dplyr::filter(.data$slice)
# grp_cols <- c("id", "fill", "alpha", "colour", "linewidth",
# "label", "size", "linetype", "render")
# data <- data %>% group_by(group_by(pick(any_of(grp_cols))))
# if (is.null(data$area)) {
# data$area <- 1
# }
# if (is.null(data$wt)) {
# data$wt <- 1
# }
# data <- data %>% summarize(area = fun(.data$area * .data$wt),
# .groups = "drop")
# data <- data %>% arrange(id)
# if (is.null(data$within)) {
# data$within <- 1
# }
# data <- data %>% group_by(.data$within) %>% mutate(prop = .data$area/sum(.data$area)) %>%
# mutate(percent = round(.data$prop * 100))
# data$id = 1:nrow(data)
# data %>% pull(area) %>% packcircles::circleProgressiveLayout(sizetype = "area") %>%
# packcircles::circleLayoutVertices(npoints = npoints) %>%
# left_join(data, by = join_by(id))
# }
Intro Thoughts
Status Quo
library(tidyverse)
ggplot(cars) +
aes(dist, speed) +
geom_point(size = 7) +
aes(color = speed) +
scale_color_viridis_c(limits = c(0,26)) +
scale_x_continuous(limits = c(0,125)) +
scale_y_continuous(limits = c(0,25))

# last_plot() %>% `%+%`(cars)
#
# update_data <- `%+%`
# last_plot() |>
# update_data(cars %>% filter(dist > 20))
last_plot_update_data <- function(p = last_plot(), data){
p$data <- data
p
}
last_plot_update_data(data = cars %>% filter(speed > 10))

last_plot_filter_data <- function(p = last_plot(), keep){
p$data <- p$data %>% filter({{keep}})
p
}
last_plot_filter_data(keep = dist > 40)

#The {magrittr} piping with . returns a function (of the 'functional sequence' subclass), so that kicks off the 'function as data' clause of the data documention.
#You could probably do something like the following to allow that in data_replace() too:
library(tidyverse)
ggplot_add.wipedata <- function(object, plot, object_name) {
new <- object$new_data_specifiction
if (is.function(new)) {
new <- new(plot$data)
}
plot$data <- new
plot
}
data_replace <- function(data) {
structure(list(new_data_specification = data),
class = "wipedata")
}
circle_packing_data <- data.frame(x = abs(rnorm(100)), id = 1:100)
circle_packing_data %>%
ggplot(data = .) +
aes(area = x, id = id) +
ggcirclepack::geom_circlepack()

last_plot() +
data_replace(data = circle_packing_data %>% mutate(x = sort(x)))
## Error in panels[[1]]: subscript out of bounds
last_plot() +
data_replace(data = . %>% mutate(x = sort(x)))
## Error in panels[[1]]: subscript out of bounds
ggplot_add.wipedata <- function(object, plot, object_name) {
plot$data <- object$new_data_specification
plot
}
last_plot() +
data_replace(data = circle_packing_data %>% mutate(x = sort(x)))

last_plot() +
data_replace(data = circle_packing_data %>% mutate(x = rev(sort(x))))

last_plot() %+%
(. %>% mutate(x = sort(x)))
## Error in `ggplot_add()`:
## ! Can't add `(. %>% mutate(x = sort(x)))` to a <ggplot> object
## ℹ Did you forget to add parentheses, as in `(. %>% mutate(x = sort(x)))()`?