@@ -54,6 +54,8 @@ markLegends <-
5454 path = c(" linetype" , " size" , " colour" , " shape" ),
5555 polygon = c(" colour" , " fill" , " linetype" , " size" , " group" ),
5656 bar = c(" colour" , " fill" ),
57+ errorbar = c(" colour" , " linetype" ),
58+ errorbarh = c(" colour" , " linetype" ),
5759 area = c(" colour" , " fill" ),
5860 step = c(" linetype" , " size" , " colour" ),
5961 boxplot = c(" x" ),
@@ -103,7 +105,6 @@ gg2list <- function(p){
103105
104106 # # Extract data from built ggplots
105107 built <- ggplot_build2(p )
106-
107108 # Get global x-range now because we need some of its info in layer2traces
108109 ggranges <- built $ panel $ ranges
109110 # Extract x.range
@@ -164,7 +165,9 @@ gg2list <- function(p){
164165 names(ranks ) <- br
165166 misc $ breaks [[sc $ aesthetics ]] <- ranks
166167 }
168+ misc $ trans [sc $ aesthetics ] <- sc $ trans $ name
167169 }
170+ reverse.aes <- names(misc $ trans )[misc $ trans == " reverse" ]
168171
169172 # # get gglayout now because we need some of its info in layer2traces
170173 gglayout <- built $ panel $ layout
@@ -180,9 +183,17 @@ gg2list <- function(p){
180183 df <- merge(df , gglayout [, c(" PANEL" , " plotly.row" , " COL" )])
181184 df <- df [order(df $ order ),]
182185 df $ order <- NULL
183-
184- misc $ prestats.data <- merge(built $ prestats.data [[i ]],
185- gglayout [, c(" PANEL" , " plotly.row" , " COL" )])
186+
187+ prestats <- built $ prestats.data [[i ]]
188+ # # scale_reverse multiples x/y data by -1, so here we undo that so
189+ # # that the actual data can be uploaded to plotly.
190+ replace.aes <- intersect(names(prestats ), reverse.aes )
191+ for (a in replace.aes ){
192+ prestats [[a ]] <- - 1 * prestats [[a ]]
193+ }
194+ misc $ prestats.data <-
195+ merge(prestats ,
196+ gglayout [, c(" PANEL" , " plotly.row" , " COL" )])
186197
187198 # Add global x-range info
188199 misc $ prestats.data $ globxmin <- ggxmin
@@ -201,7 +212,8 @@ gg2list <- function(p){
201212 traces <- layer2traces(L , df , misc )
202213
203214 # Associate error bars with previous traces
204- if (grepl(" errorbar" , L $ geom $ objname )) {
215+ # #if (grepl("errorbar", L$geom$objname)) { #TDH 28 Jan 2015.
216+ if (FALSE ){
205217 for (j in 1 : length(trace.list )) {
206218 temp <- list ()
207219 ind <- traces [[1 ]]$ x %in% trace.list [[j ]]$ x
@@ -274,6 +286,8 @@ gg2list <- function(p){
274286 cls <- attr(e(el.name )," class" )
275287 " element_blank" %in% cls || null.is.blank && is.null(cls )
276288 }
289+ trace.order.list <- list ()
290+ trace.name.map <- c()
277291 for (xy in c(" x" ," y" )){
278292 ax.list <- list ()
279293 s <- function (tmp )sprintf(tmp , xy )
@@ -324,6 +338,29 @@ gg2list <- function(p){
324338 scale.i <- which(p $ scales $ find(xy ))
325339 ax.list $ title <- if (length(scale.i )){
326340 sc <- p $ scales $ scales [[scale.i ]]
341+ trace.order.list [[xy ]] <- sc $ limits
342+ trace.name.map [sc $ breaks ] <- sc $ labels
343+ if (is.null(sc $ breaks )){
344+ ax.list $ showticklabels <- FALSE
345+ ax.list $ showgrid <- FALSE
346+ ax.list $ ticks <- " "
347+ }
348+ if (is.numeric(sc $ breaks )){
349+ dticks <- diff(sc $ breaks )
350+ dt <- dticks [1 ]
351+ if (all(dticks == dt )){
352+ ax.list $ dtick <- dt
353+ ax.list $ autotick <- FALSE
354+ }
355+ }
356+ ax.list $ range <- if (! is.null(sc $ limits )){
357+ sc $ limits
358+ }else {
359+ ggranges [[1 ]][[s(" %s.range" )]] # TODO: facets!
360+ }
361+ if (is.character(sc $ trans $ name ) && sc $ trans $ name == " reverse" ){
362+ ax.list $ range <- sort(- ax.list $ range , decreasing = TRUE )
363+ }
327364 if (! is.null(sc $ name )){
328365 sc $ name
329366 }else {
@@ -332,6 +369,7 @@ gg2list <- function(p){
332369 }else {
333370 p $ labels [[xy ]]
334371 }
372+
335373 title.text <- e(s(" axis.title.%s" ))
336374 ax.list $ titlefont <- theme2font(title.text )
337375 ax.list $ type <- if (misc $ is.continuous [[xy ]]){
@@ -643,63 +681,103 @@ gg2list <- function(p){
643681 layout $ legend $ bgcolor <- toRGB(s(rect_fill ))
644682 }
645683
646- trace.list $ kwargs <- list (layout = layout )
647-
648- if (length(trace.list ) < 2 ) {
684+ if (length(trace.list ) == 0 ) {
649685 stop(" No exportable traces" )
650686 }
651-
652- if (length(trace.list ) > 2 ) {
653- # Maybe some traces should be merged.
654- nr <- length(trace.list ) - 1
655- comp <- data.frame (matrix (ncol = 2 , nrow = nr ))
656- colnames(comp ) <- c(" name" , " mode" )
657-
658- for (j in 1 : nr ) {
659- # Use lapply to be elegant?
660- for (d in colnames(comp )) {
661- try(comp [[d ]][j ] <- trace.list [[j ]][[d ]], silent = TRUE )
662- # "names" might be NULL in trace.list
687+
688+ mode.mat <- matrix (NA , 3 , 3 )
689+ rownames(mode.mat ) <- colnames(mode.mat ) <- c(" markers" , " lines" , " none" )
690+ mode.mat [" markers" , " lines" ] <-
691+ mode.mat [" lines" , " markers" ] <- " lines+markers"
692+ mode.mat [" markers" , " none" ] <- mode.mat [" none" , " markers" ] <- " markers"
693+ mode.mat [" lines" , " none" ] <- mode.mat [" none" , " lines" ] <- " lines"
694+ merged.traces <- list ()
695+ not.merged <- trace.list
696+ while (length(not.merged )){
697+ tr <- not.merged [[1 ]]
698+ not.merged <- not.merged [- 1 ]
699+ # # Are there any traces that have not yet been merged, and can be
700+ # # merged with tr?
701+ can.merge <- rep(FALSE , l = length(not.merged ))
702+ for (other.i in seq_along(not.merged )){
703+ other <- not.merged [[other.i ]]
704+ criteria <- c()
705+ for (must.be.equal in c(" x" , " y" , " xaxis" , " yaxis" )){
706+ other.attr <- other [[must.be.equal ]]
707+ tr.attr <- tr [[must.be.equal ]]
708+ criteria [[must.be.equal ]] <- isTRUE(all.equal(other.attr , tr.attr ))
709+ }
710+ if (all(criteria )){
711+ can.merge [[other.i ]] <- TRUE
663712 }
664713 }
665- # Compare the "name"s of the traces (so far naively inherited from layers)
666- layernames <- unique(comp $ name )
667- if (length(layernames ) < nr ) {
668- # Some traces (layers at this stage) have the same "name"s.
669- for (j in 1 : length(layernames )) {
670- lind <- which(layernames [j ] == comp $ name )
671- lmod <- c(" lines" , " markers" ) %in% comp $ mode [lind ]
672- # Is there one with "mode": "lines" and another with "mode": "markers"?
673- if (all(lmod )) {
674- # Data comparison
675- xcomp <- (trace.list [[lind [1 ]]]$ x == trace.list [[lind [2 ]]]$ x )
676- ycomp <- (trace.list [[lind [1 ]]]$ y == trace.list [[lind [2 ]]]$ y )
677- if (all(xcomp ) && all(ycomp )) {
678- # Union of the two traces
679- keys <- unique(c(names(trace.list [[lind [1 ]]]),
680- names(trace.list [[lind [2 ]]])))
681- temp <- setNames(mapply(c , trace.list [[lind [1 ]]][keys ],
682- trace.list [[lind [2 ]]][keys ]), keys )
683- # Info is duplicated in fields which are in common
684- temp <- lapply(temp , unique )
685- # But unique() is detrimental to line or marker sublist
686- temp $ line <- trace.list [[lind [1 ]]]$ line
687- temp $ marker <- trace.list [[lind [2 ]]]$ marker
688- # Overwrite x and y to be safe
689- temp $ x <- trace.list [[lind [1 ]]]$ x
690- temp $ y <- trace.list [[lind [1 ]]]$ y
691- # Specify new one mode
692- temp $ mode <- " lines+markers"
693- # Keep one trace and remove the other one
694- trace.list [[lind [1 ]]] <- temp
695- trace.list <- trace.list [- lind [2 ]]
696- # Update comparison table
697- comp <- comp [- lind [2 ], ]
698- }
714+ to.merge <- not.merged [can.merge ]
715+ not.merged <- not.merged [! can.merge ]
716+ for (other in to.merge ){
717+ new.mode <- tryCatch({
718+ mode.mat [tr $ mode , other $ mode ]
719+ }, error = function (e ){
720+ NA
721+ })
722+ if (is.character(new.mode ) && ! is.na(new.mode )){
723+ tr $ mode <- new.mode
724+ }
725+ attrs <- c(" error_x" , " error_y" , " marker" , " line" )
726+ for (attr in attrs ){
727+ if (! is.null(other [[attr ]]) && is.null(tr [[attr ]])){
728+ tr [[attr ]] <- other [[attr ]]
699729 }
700730 }
701731 }
732+ merged.traces [[length(merged.traces )+ 1 ]] <- tr
702733 }
734+
735+ # # Put the traces in correct order, according to any manually
736+ # # specified scales.
737+ trace.order <- unlist(trace.order.list )
738+ ordered.traces <- if (length(trace.order )){
739+ trace.order.score <- seq_along(trace.order )
740+ names(trace.order.score ) <- trace.order
741+ trace.name <- sapply(merged.traces , " [[" , " name" )
742+ trace.score <- trace.order.score [trace.name ]
743+ merged.traces [order(trace.score )]
744+ }else {
745+ merged.traces
746+ }
747+
748+ # # Translate scale(labels) to trace name.
749+ named.traces <- ordered.traces
750+ for (trace.i in seq_along(named.traces )){
751+ tr.name <- named.traces [[trace.i ]][[" name" ]]
752+ new.name <- trace.name.map [[tr.name ]]
753+ if (! is.null(new.name )){
754+ named.traces [[trace.i ]][[" name" ]] <- new.name
755+ }
756+ }
757+
758+ # # If coord_flip is defined, then flip x/y in each trace, and in
759+ # # each axis.
760+ flipped.traces <- named.traces
761+ flipped.layout <- layout
762+ if (" flip" %in% attr(built $ plot $ coordinates , " class" )){
763+ if (! inherits(p $ facet , " null" )){
764+ stop(" coord_flip + facet conversion not supported" )
765+ }
766+ for (trace.i in seq_along(flipped.traces )){
767+ tr <- flipped.traces [[trace.i ]]
768+ x <- tr [[" x" ]]
769+ y <- tr [[" y" ]]
770+ tr [[" y" ]] <- x
771+ tr [[" x" ]] <- y
772+ flipped.traces [[trace.i ]] <- tr
773+ }
774+ x <- layout [[" xaxis" ]]
775+ y <- layout [[" yaxis" ]]
776+ flipped.layout [[" xaxis" ]] <- y
777+ flipped.layout [[" yaxis" ]] <- x
778+ }
779+
780+ flipped.traces $ kwargs <- list (layout = flipped.layout )
703781
704- trace.list
782+ flipped.traces
705783}
0 commit comments