Skip to content

Commit 73d07c9

Browse files
committed
Merge pull request #50 from ropensci/marianne-histogram
Conversion for geom_histogram
2 parents 8ef0e0b + 78aac12 commit 73d07c9

File tree

2 files changed

+80
-12
lines changed

2 files changed

+80
-12
lines changed

R/ggplotly.R

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,19 @@ toBasic <-
128128
},line=function(g){
129129
g$data <- g$data[order(g$data$x),]
130130
group2NA(g, "path")
131-
},ribbon=function(g){
131+
},
132+
histogram=function(g) {
133+
bin_start <- min(g$data$xmin)
134+
bin_end <- max(g$data$xmax)
135+
xdim <- g$aes[["x"]]
136+
g$data <- NULL
137+
g$data$x <- g$plot[[xdim]]
138+
g$plot <- NULL
139+
g$params$xstart <- bin_start
140+
g$params$xend <- bin_end
141+
g
142+
},
143+
ribbon=function(g){
132144
stop("TODO")
133145
})
134146

@@ -182,6 +194,22 @@ geom2trace <-
182194
type="scatter",
183195
mode="lines",
184196
line=paramORdefault(params, aes2line, line.defaults))
197+
},
198+
histogram=function(data, params) {
199+
L <- list(x=data$x,
200+
name=params$name,
201+
text=data$text,
202+
type="histogram",
203+
fillcolor=toRGB(params$fill))
204+
if (is.null(params$binwidth)) {
205+
L$autobinx <- TRUE
206+
} else {
207+
L$autobinx <- FALSE
208+
L$xbins=list(start=params$xstart,
209+
end=params$xend,
210+
size=params$binwidth)
211+
}
212+
L
185213
}
186214
)
187215

@@ -197,7 +225,8 @@ markLegends <-
197225
path=c("linetype", "size", "colour"),
198226
polygon=c("colour", "fill", "linetype", "size", "group"),
199227
bar=c("fill"),
200-
step=c("linetype", "size", "colour"))
228+
step=c("linetype", "size", "colour"),
229+
histogram=c("colour", "fill"))
201230

202231
markUnique <- as.character(unique(unlist(markLegends)))
203232

@@ -239,17 +268,19 @@ gg2list <- function(p){
239268
p$layers[[layer.i]]$data <- p$data
240269
}
241270
}
242-
geom_type <- p$layers[[layer.i]]$geom
243-
geom_type <- strsplit(capture.output(geom_type), "geom_")[[1]][2]
244-
geom_type <- strsplit(geom_type, ": ")[[1]]
271+
272+
geom_type <- p$layers[[layer.i]]$geom$objname
245273
## Barmode.
246274
layout$barmode <- "group"
247275
if (geom_type == "bar") {
248276
stat_type <- capture.output(p$layers[[layer.i]]$stat)
249277
stat_type <- strsplit(stat_type, ": ")[[1]]
250-
if (!grepl("identity", stat_type)) {
251-
stop("Conversion not implemented for ", stat_type)
278+
if (grepl("bin", stat_type)) {
279+
geom_type <- "histogram"
280+
warning("You may want to use geom_histogram.")
252281
}
282+
}
283+
if (geom_type == "bar" || geom_type == "histogram") {
253284
pos <- capture.output(p$layers[[layer.i]]$position)
254285
if (grepl("identity", pos)) {
255286
layout$barmode <- "overlay"
@@ -260,6 +291,12 @@ gg2list <- function(p){
260291

261292
## Extract data from built ggplots
262293
built <- ggplot2::ggplot_build(p)
294+
295+
if (geom_type == "histogram") {
296+
# Need actual data (distribution)
297+
trace.list$plot <- built$plot$data
298+
}
299+
263300
ranges <- built$panel$ranges[[1]]
264301
for(i in seq_along(built$plot$layers)){
265302
## This is the layer from the original ggplot object.
@@ -306,7 +343,7 @@ gg2list <- function(p){
306343
}
307344

308345
## This extracts essential info for this geom/layer.
309-
traces <- layer2traces(L, df, misc)
346+
traces <- layer2traces(L, df, misc, trace.list$plot)
310347

311348
## Do we really need to coord_transform?
312349
##g$data <- ggplot2:::coord_transform(built$plot$coord, g$data,
@@ -412,6 +449,7 @@ gg2list <- function(p){
412449
if(length(trace.list) == 1){
413450
stop("No exportable traces")
414451
}
452+
trace.list$plot <- NULL
415453
trace.list
416454
}
417455

@@ -421,9 +459,10 @@ gg2list <- function(p){
421459
#' @param misc named list.
422460
#' @return list representing a layer, with corresponding aesthetics, ranges, and groups.
423461
#' @export
424-
layer2traces <- function(l, d, misc){
462+
layer2traces <- function(l, d, misc, plot=NULL){
425463
g <- list(geom=l$geom$objname,
426-
data=d)
464+
data=d,
465+
plot=plot)
427466
## needed for when group, etc. is an expression.
428467
g$aes <- sapply(l$mapping, function(k) as.character(as.expression(k)))
429468

@@ -438,6 +477,10 @@ layer2traces <- function(l, d, misc){
438477
data.vec <- l$data[[col.name]]
439478
if(inherits(data.vec, "POSIXt")){
440479
data.vec <- strftime(data.vec, "%Y-%m-%d %H:%M:%S")
480+
} else if (inherits(data.vec, "factor")) {
481+
## Re-order data so that Plotly gets it right from ggplot2.
482+
g$data <- g$data[order(g$data[[a]]),]
483+
data.vec <- data.vec[match(g$data[[a]], as.numeric(data.vec))]
441484
}
442485
g$data[[a]] <- data.vec
443486
}
@@ -532,9 +575,9 @@ layer2traces <- function(l, d, misc){
532575
for(data.i in seq_along(data.list)){
533576
data.params <- data.list[[data.i]]
534577
tr <- do.call(getTrace, data.params)
535-
for(v.name in c("x", "y")){
578+
for (v.name in c("x", "y")) {
536579
vals <- tr[[v.name]]
537-
if(is.na(vals[length(vals)])){
580+
if (length(vals) > 0 && is.na(vals[length(vals)])) {
538581
tr[[v.name]] <- vals[-length(vals)]
539582
}
540583
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
context("Histogram")
2+
3+
# Non-numeric data
4+
noram <- data.frame(country=c("MEX", "CDN", "USA", "CDN", "MEX", "MEX"))
5+
6+
test_that("default position is translated to barmode=stack", {
7+
hist <- ggplot(noram, aes(country)) + geom_bar()
8+
L <- gg2list(hist)
9+
expect_equal(length(L), 2)
10+
expect_identical(L$kwargs$layout$barmode, "stack")
11+
})
12+
13+
# Numeric data
14+
x <- rnorm(50)
15+
df <- data.frame(index=seq(1:length(x)), x=x)
16+
# Binwidth
17+
bw <- 0.8
18+
gg <- ggplot(df, aes(x))
19+
20+
test_that("binwidth is translated into xbins.size", {
21+
hist <- gg + geom_histogram(binwidth=bw)
22+
L <- gg2list(hist)
23+
expect_equal(length(L), 2)
24+
expect_equal(L[[1]]$xbins$size, bw)
25+
})

0 commit comments

Comments
 (0)