I want to use ggplot2 with grid.arrange to generate multiple plots with plotly.
Some thing similar to this:
library(ggplot2)
library(gridExtra)
library(plotly)
g1<-ggplot(mpg, aes(displ, hwy, color=factor(year)))+geom_point()
g2<-ggplot(mpg, aes(cyl, hwy, color=factor(year)))+geom_point()
g<-grid.arrange(g1,g2,ncol=2)
ggplotly(g)
However, I am getting "Error in gg2list(p) : No layers in plot"
Any suggestions
Use the subplot function of plotly:
subplot(p1, p2, nrows = 2, margin = 0.04, heights = c(0.6, 0.4))
I'm having this problem myself and I don't think a solution currently exists to do this in the way you're describing.
The gg2list function contained in the call to ggplotly expects to be able to iterate over a ggplot object's layers to create the corresponding plotly object. If you step into the ggplotly function with RStudio's debugger, you can see the various ways in which it attempts to iterate across the object it receives in order to extract its properties.
It doesn't know what to do with the object returned by the arrangeGrob function because it's not just a single ggplot object (it's a grob arrangement, etc).
Calling class() on the objects in question illustrates this point somewhat.
> class(g1)
[1] "gg" "ggplot"
> class(g)
[1] "arrange" "ggplot" "gTree" "grob" "gDesc"
I think in order to have multiple plots heads up in the same plotly object, we will need to use the facet options in ggplot or the native plotly R bindings. Unfortunate, because gridExtra is very powerful and flexible, but the ggplot translation mechanism doesn't seem to be able to handle it.
Related
I expect this kind of scatter plot.
However, whenever I tried to apply on my data, I get this.
I just used this code, and this is my data.
And I also confirmed they are numeric class.
ggplot(selected.df, aes(x, y))
making a right plot.
Those variables were not numeric.
I have build up a dendrogram and colored its branches according to their "purity" (whether they only include subjects with a particular value in a factor variable) using the set("by_labels_branches_col") function of the dendextend package. Now, I would like to convert this dendrogram to a ggplot2 object for further customization. I have been able to do that with the function as.ggdend (also from the dendextend package). Here is when I encounter 2 issues
for which I would need some help:
1-After using as.ggdend, the resulting object "loses" the vertical axis indicating the height of the dendrogram... How could I do this transformation without losing the axis?
2.-I have also tried to enrich my dendrogram by adding a colored bar using the colored_bars function of the dendextend package. However, I do not know how to save the resulting object to convert it to a ggplot object.
Here I provide an example of my code with the mtcars dataset
df=mtcars
ds=dist(df, "euclidean")
hc<-hclust(ds,method= "average")
de=as.dendrogram(hc)
library(dendextend)
code=rownames(df[df$cyl==4,])#factor for coloring
de2<-de%>%set("by_labels_branches_col", value = c(code))%>% set("labels", "")%>%as.dendrogram(de)#coloring branches
#to add the colored bar
colores<-c("red","black", "blue") [as.factor(df$cyl)]
plot(de2)
colored_bars(colors=colores,dend=de2, y_shift=-2, rowLabels="" )
#transform to ggplot
de3=as.ggdend(de2)
Thanks in advance for any possible answer
Finally, I have found a solution for the first of the posted questions). It is far from elegant and probably there are better ways to do this. However, I post it here just in case someone finds it useful.
The solution skips the use of as.ggdend and directly uses ggplot+theme to ensure that the dendrogram axis is displayed. Because this automatically thickens all plot lines, line sizes are corrected at steps 2/3.
step1=ggplot(de2)+
theme(axis.line.y = element_line(color="black"),
axis.text.y = element_text(color="black"),
axis.ticks.y = element_line(color="black"))+
scale_y_continuous(expand = expansion(add = c(0,0)))
step2=ggplot_build(step1)
step2$data[[1]]$size=0.3
step3= ggplot_gtable(step2)
step4=ggplotify::as.ggplot(step3)
I've been trying to edit some plots created by ggplot2 using the functions provided by the packages grid and gridExtra. I realize that ggplot2 alone can make some really nice multifaceted plots. However, in some instances I like to create individual plots and then combine then together later on. While trying to do just that, I came across some unexpected behavior using cbind() with grid.draw() or grid.arrange() when using a ggplot2 graph that had been edited. Below is the code for an MWE:
#Load libraries
library(ggplot2); library(gridExtra)
#Load data
data(mtcars)
#Ggplot
p = qplot(wt,mpg,data=mtcars,color=cyl)
grob = ggplotGrob(p)
#Bold xlabel
grobEdited = editGrob(grid.force(grob),gPath("xlab","GRID.text"),grep=TRUE,gp=gpar(fontface="bold"))
#Visualize
grid.newpage()
grid.draw(grobEdited)
It worked as expected. Now to illustrate the issue, lets cbind() two of the same edited ggplot2 graphs:
#Cbind example with edited graphs
grid.newpage()
grid.draw(cbind(grobEdited,grobEdited))
It didn't work as expected! Now test cbind() on the unedited graphs:
#Cbind example with grob
grid.newpage()
grid.draw(cbind(grob,grob))
Works as expected. I'm new to gridded figures, so is there something I'm doing wrong?
I'm posting an answer following the comment from #user20650. The easiest workaround is to cbind() the ggplot2 graphs before editing them using the editing functions provided by grid or gridExtra:
#Edit after cbind()
grobEdited = editGrob(grid.force(cbind(grob,grob)),gPath("xlab","GRID.text"),global=TRUE,grep=TRUE,gp=gpar(fontface="bold"))
#Visualize
grid.newpage()
grid.draw(grobEdited)
Currently, I am trying to transition my graphical knowledge from the plot function in R, to the ggplot function. I have began constructing scatterplots and corresponding legends for a given data set, however I want to incorporate the function geom_polygon onto my plots using ggplot.
Specifically, I want to capture a triangular region from the origin of a scatterplot. For reproducibility, say I have the following data set:
rawdata<-data.frame(matrix(c(1,1,1,
2,1,-1,
3,-1,-1,
4,-1,1,
4,-2,2),5,3,byrow=TRUE))
names(rawdata)<-c("Town","x.coordinate","y.coordinate")
rawdata[,1]<-as.factor(rawdata[,1])
To construct a scatterplot along with a legend, I have been told to do the following:
p1<-ggplot(data=rawdata,aes(x=x.coordinate,y=y.coordinate,colour=Town,shape=Town))
+ theme_bw() + geom_point()
The result is the following:
Click here.
What I want to do now is produce a polygon. To do so, I have construct the following dataframe to use in the geom_polygon function:
geom_polygon(data=polygondata,aes(x = xa, y = ya),colour="darkslategray2",
fill = "darkslategray2",alpha=0.25)
However, when I combine this with p1, I get the following error:
Error in eval(expr, envir, enclos) : object 'Town' not found
From some messing around, I have noticed that when I omit the shape argument from the ggplot function, I can easily produce the desired output which is shown here. However, I wish to keep the shape for aesthetics.
I also get a similar problem when I try to produce arrows which connect points on the scatterplot using ggplot. However, I will address this problem after, as the root problem may be here.
Add the following to polygondata:
polygondata$Town = NA
Even though you're not using that variable in geom_polygon, ggplot expects it to be there if that column is used for an aesthetic in the main call to ggplot.
Alternatively, I think you could avoid the error if you move the aesthetic mapping in the initial plot to geom_point rather than the main ggplot call, like this:
p1 <- ggplot(data=rawdata) +
theme_bw() +
geom_point(aes(x=x.coordinate, y=y.coordinate, colour=Town, shape=Town))
In that case, you wouldn't need to add a Town column to polygondata.
I am modifying a graph built with ggplot by altering the data produced by ggplot_build (for a reason similar to Include space for missing factor level used in fill aesthetics in geom_boxplot). As far as I understand the help I found on this topic, I should be able to save the result by applying ggplot_gtable and arrangeGrob before calling ggsave on the results (Saving grid.arrange() plot to file).
However I obtain an error "plot should be a ggplot2 plot", also with this simple reproductible example:
require('ggplot2')
require('gridExtra')
df <- data.frame(f1=factor(rbinom(100, 1, 0.45), label=c("m","w")),
f2=factor(rbinom(100, 1, 0.45), label=c("young","old")),
boxthis=rnorm(100))
g <- ggplot(aes(y = boxthis, x = f2, fill = f1), data = df) + geom_boxplot()
dd <- ggplot_build(g)
# Printing the graph works:
print(arrangeGrob(ggplot_gtable(dd)))
# Saving the graph doesn't:
ggsave('test.png',arrangeGrob(ggplot_gtable(dd)))
Can anybody explain why this does not work ? Is there a way to use ggsave after modifying the data by using ggplot_build() ?
(My version of the packages are gridExtra_0.9.1 and ggplot2_0.9.3.1)
it does not work because ggsave wants an object of class ggplot, while you're passing a grob. arrangeGrob will sometimes trick ggsave in pretending inheritance from ggplot, but only when at least one of the grobs belongs to this class; here, however, you're only passing a gtable.
Perhaps the easiest workaround is to clone ggsave and bypass the class check,
ggsave <- ggplot2::ggsave; body(ggsave) <- body(ggplot2::ggsave)[-2]
Edit: The dev version of ggplot2 no longer requires this hack*, as ggsave now works with any grob.
*PS: this hack works no longer, as arrangeGrob now returns a gtable, and its print method does not draw on a device.
A work around is to plot the gtable object with grid.draw() and then use dev.copy() to transfer the plot to a file.
Remember to use also dev.off() just afterward.