-
Notifications
You must be signed in to change notification settings - Fork 633
Toby cookbook lines #196
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
Toby cookbook lines #196
Changes from 5 commits
e47ca93
3ef9be5
b60d935
1bea709
8e68d8a
305ad6c
7308760
6c72262
84ab366
6318787
4a2dc57
a4d0059
4a7f713
56ede93
3105143
bd8c3f6
5fa2434
96f0d40
f0eb05e
8f937e0
9ab52e1
f90928b
d142570
ab4ca1c
498455d
4cfedf9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -97,8 +97,10 @@ gg2list <- function(p){ | |
# worry about combining global and layer-specific aes/data later. | ||
for(layer.i in seq_along(p$layers)) { | ||
layer.aes <- p$layers[[layer.i]]$mapping | ||
to.copy <- names(p$mapping)[!names(p$mapping) %in% names(layer.aes)] | ||
layer.aes[to.copy] <- p$mapping[to.copy] | ||
if(p$layers[[layer.i]]$inherit.aes){ | ||
to.copy <- names(p$mapping)[!names(p$mapping) %in% names(layer.aes)] | ||
layer.aes[to.copy] <- p$mapping[to.copy] | ||
} | ||
mark.names <- markUnique[markUnique %in% names(layer.aes)] | ||
name.names <- sprintf("%s.name", mark.names) | ||
layer.aes[name.names] <- layer.aes[mark.names] | ||
|
@@ -107,19 +109,73 @@ gg2list <- function(p){ | |
p$layers[[layer.i]]$data <- p$data | ||
} | ||
} | ||
|
||
## Test fill and color to see if they encode a quantitative | ||
## variable. This may be useful for several reasons: (1) it is | ||
## sometimes possible to plot several different colors in the same | ||
## trace (e.g. points), and that is faster for large numbers of | ||
## data points and colors; (2) factors on x or y axes should be | ||
## sent to plotly as characters, not as numeric data (which is | ||
## what ggplot_build gives us). | ||
misc <- list() | ||
for(a in c("fill", "colour", "x", "y", "size")){ | ||
for(data.type in c("continuous", "date", "datetime", "discrete")){ | ||
fun.name <- sprintf("scale_%s_%s", a, data.type) | ||
misc.name <- paste0("is.", data.type) | ||
misc[[misc.name]][[a]] <- tryCatch({ | ||
fun <- get(fun.name) | ||
suppressMessages({ | ||
with.scale <- original.p + fun() | ||
}) | ||
ggplot_build(with.scale) | ||
TRUE | ||
}, error=function(e){ | ||
FALSE | ||
}) | ||
} | ||
} | ||
|
||
## scales are needed for legend ordering. | ||
misc$breaks <- list() | ||
for(sc in p$scales$scales){ | ||
a.vec <- sc$aesthetics | ||
default.breaks <- inherits(sc$breaks, "waiver") | ||
if (length(a.vec) == 1 && (!default.breaks) ) { | ||
## TODO: generalize for x/y scales too. | ||
br <- sc$breaks | ||
ranks <- seq_along(br) | ||
names(ranks) <- br | ||
misc$breaks[[a.vec]] <- ranks | ||
} | ||
## store if this is a reverse scale so we can undo that later. | ||
if(is.character(sc$trans$name)){ | ||
misc$trans[sc$aesthetics] <- sc$trans$name | ||
} | ||
} | ||
reverse.aes <- names(misc$trans)[misc$trans=="reverse"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this whole block which creates misc was inside the for(layer.i) block below, which is potentially confusing, since misc contains plot-specific, not layer-specific, information. |
||
|
||
# Extract data from built ggplots | ||
built <- ggplot_build2(p) | ||
# Get global x-range now because we need some of its info in layer2traces | ||
ggranges <- built$panel$ranges | ||
# Extract x.range | ||
xrange <- sapply(ggranges, `[[`, "x.range", simplify=FALSE, USE.NAMES=FALSE) | ||
ggxmin <- min(sapply(xrange, min)) | ||
ggxmax <- max(sapply(xrange, max)) | ||
# Extract y.range | ||
yrange <- sapply(ggranges, `[[`, "y.range", simplify=FALSE, USE.NAMES=FALSE) | ||
ggymin <- min(sapply(yrange, min)) | ||
ggymax <- max(sapply(yrange, max)) | ||
# Get global ranges now because we need some of its info in layer2traces | ||
ranges.list <- list() | ||
for(xy in c("x", "y")){ | ||
use.ranges <- | ||
misc$is.continuous[[xy]] | | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should probably use |
||
misc$is.date[[xy]] | | ||
misc$is.datetime[[xy]] | ||
range.values <- if(use.ranges){ | ||
range.name <- paste0(xy, ".range") | ||
sapply(built$panel$ranges, "[[", range.name) | ||
}else{ | ||
## for categorical variables on the axes, panel$ranges info is | ||
## meaningless. | ||
name.name <- paste0(xy, ".name") | ||
sapply(built$data, function(df){ | ||
paste(df[[name.name]]) | ||
}) | ||
} | ||
ranges.list[[xy]] <- range(range.values) | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getting global ranges is more complicated now that we respect inherit.aes |
||
|
||
# Get global size range because we need some of its info in layer2traces | ||
if ("size.name" %in% name.names) { | ||
|
@@ -135,51 +191,7 @@ gg2list <- function(p){ | |
|
||
# for each layer, there is a correpsonding data.frame which | ||
# evaluates the aesthetic mapping. | ||
df <- built$data[[i]] | ||
|
||
# Test fill and color to see if they encode a quantitative | ||
# variable. This may be useful for several reasons: (1) it is | ||
# sometimes possible to plot several different colors in the same | ||
# trace (e.g. points), and that is faster for large numbers of | ||
# data points and colors; (2) factors on x or y axes should be | ||
# sent to plotly as characters, not as numeric data (which is | ||
# what ggplot_build gives us). | ||
misc <- list() | ||
for(a in c("fill", "colour", "x", "y", "size")){ | ||
for(data.type in c("continuous", "date", "datetime", "discrete")){ | ||
fun.name <- sprintf("scale_%s_%s", a, data.type) | ||
misc.name <- paste0("is.", data.type) | ||
misc[[misc.name]][[a]] <- tryCatch({ | ||
fun <- get(fun.name) | ||
suppressMessages({ | ||
with.scale <- original.p + fun() | ||
}) | ||
ggplot_build(with.scale) | ||
TRUE | ||
}, error=function(e){ | ||
FALSE | ||
}) | ||
} | ||
} | ||
|
||
# scales are needed for legend ordering. | ||
misc$breaks <- list() | ||
for(sc in p$scales$scales){ | ||
a.vec <- sc$aesthetics | ||
default.breaks <- inherits(sc$breaks, "waiver") | ||
if (length(a.vec) == 1 && (!default.breaks) ) { | ||
# TODO: generalize for x/y scales too. | ||
br <- sc$breaks | ||
ranks <- seq_along(br) | ||
names(ranks) <- br | ||
misc$breaks[[a.vec]] <- ranks | ||
} | ||
## store if this is a reverse scale so we can undo that later. | ||
if(is.character(sc$trans$name)){ | ||
misc$trans[sc$aesthetics] <- sc$trans$name | ||
} | ||
} | ||
reverse.aes <- names(misc$trans)[misc$trans=="reverse"] | ||
df <- built$data[[i]] | ||
|
||
# get gglayout now because we need some of its info in layer2traces | ||
gglayout <- built$panel$layout | ||
|
@@ -203,21 +215,24 @@ gg2list <- function(p){ | |
for (a in replace.aes) { | ||
prestats[[a]] <- -1 * prestats[[a]] | ||
} | ||
misc$prestats.data <- | ||
L$prestats.data <- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. prestats.data is layer-specific (misc is plot-specific) |
||
merge(prestats, | ||
gglayout[, c("PANEL", "plotly.row", "COL")]) | ||
|
||
# Add global x-range info | ||
misc$prestats.data$globxmin <- ggxmin | ||
misc$prestats.data$globxmax <- ggxmax | ||
# Add global y-range info | ||
misc$prestats.data$globymin <- ggymin | ||
misc$prestats.data$globymax <- ggymax | ||
|
||
# Add global range info. | ||
for(xy in names(ranges.list)){ | ||
range.vec <- ranges.list[[xy]] | ||
names(range.vec) <- c("min", "max") | ||
for(range.name in names(range.vec)){ | ||
glob.name <- paste0("glob", xy, range.name) | ||
L$prestats.data[[glob.name]] <- range.vec[[range.name]] | ||
} | ||
} | ||
|
||
# Add global size info if relevant | ||
if ("size.name" %in% name.names) { | ||
misc$prestats.data$globsizemin <- ggsizemin | ||
misc$prestats.data$globsizemax <- ggsizemax | ||
L$prestats.data$globsizemin <- ggsizemin | ||
L$prestats.data$globsizemax <- ggsizemax | ||
} | ||
|
||
# This extracts essential info for this geom/layer. | ||
|
@@ -380,7 +395,7 @@ gg2list <- function(p){ | |
sc$limits | ||
}else{ | ||
if(misc$is.continuous[[xy]]){ | ||
ggranges[[1]][[s("%s.range")]] #TODO: facets! | ||
built$panel$ranges[[1]][[s("%s.range")]] #TODO: facets! | ||
}else{ # for a discrete scale, range should be NULL. | ||
NULL | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some geoms (like hline and vline) need to ignore the global aes mapping.