Remove empty factors from clustered bargraph in ggplot2 with multiple facets - r

I am trying to make a better version of an R base plot with ggplot2. Not only to have a common legend but also because I like the ggplot2 styles and customization. My data consists of 3 seperate datasets that contain the same two groups of observations for several (but different) treatments. Hence I want to generate 3 separate plots in 1 graph with a common legend however with different factor levels. To illustrate my point the first image here is what I have generated with R base so far:
I tried to generate a ggplot2 plot with dummy data that has exactly the same structure as my data:
foo<-data.frame(c(letters,letters),c(rep('T1',26),rep('T2',26)),
runif(52),rep(c(rep('Ori1',12),rep('Ori2',8),rep('ori3',6)),2))
names(foo)<-c('Treatment','Type','Count','Origin')
a<-ggplot(foo,aes(x = factor(Treatment),y = Count))
a+ facet_grid(Origin~., scales="free_y", space="free") +
geom_bar(stat="identity",aes(fill=factor(foo$Type)),position="dodge")
+theme_bw()+theme(axis.text.x=element_text(angle=60,hjust=1))+coord_flip()
Which gives me the following undesirable result.
I am aware of the stack overflow topics Removing Unused Factors from a Facet in ggplot2 and How can I remove empty factors from ggplot2 facets? however, they do not deal with the clustered bar graphs I try to realise here and I feel they are the problem, however do not now how to solve it. All pointers are welcome.

To illustrate my comment:
a<-ggplot(foo,aes(x = factor(Treatment),y = Count))
a+ facet_wrap(~Origin, scales="free_x") +
geom_bar(stat="identity",aes(fill=factor(Type)),position="dodge") +
theme_bw() +
theme(axis.text.x=element_text(angle=60,hjust=1))
Note that if you add coord_flip and switch to free_y you get a specific error about coord_flip not working with some types of free scales, which is the source of you problem.

Related

Creating a multi-panel plot of a data set grouped by two grouping variables in R

I'm trying to solve the following exercise:
Make a scatter plot of the relationship between the variables 'K1' and 'K2' with "faceting" based on the parameters 'diam' and 'na' (subdivide the canvas by these two variables). Finally, assign different colors to the points depending on the 'thickness' of the ring (don't forget to factor it before). The graph should be similar to this one ("grosor" stands by "thickness"):
Now, the last code I tried with is the following one (the dataset is called "qerat"):
ggplot(qerat, aes(K1,K2, fill=factor(grosor))) + geom_point() + facet_wrap(vars(diam,na))
¿Could somebody give me a hand pointing out where the mistake is? ¡Many thanks in advance!
Maybe you are looking for a facet_grid() approach. Here the code using a data similar to yours:
library(ggplot2)
#Data
data("diamonds")
#Plot
ggplot(diamonds,aes(x=carat,y=price,color=factor(cut)))+
geom_point()+
facet_grid(color~clarity)
Output:
In the case of your code, as no data is present, I would suggest next changes:
#Code
ggplot(qerat, aes(K1,K2, color=factor(grosor)))+
geom_point() +
facet_grid(diam~na)

How to create a stacked and grouped bar chart from two data frames?

I have a stacked barchart that looks like this.
If I have a second dataframe that has the same layout as the one that created the plot, and I want to group both datasets by position while still keeping the stacked percentages, how would I go about this. I'm not sure how to do it in ggplot2
Hard to say without seeing the data and without more information about what you actually want to achieve, but the general approach I would use is to say combine your dataframes - especially if the variables are the same. You just want to make sure to maintain "where" each dataset originated, and that will be your identifying column.
So, if your data is in myData1 and myData2:
# add identifying columns
myData1$id <- 'dataset1'
myData2$id <- 'dataset2'
# put them together
newData <- rbind(myData1, myData2)
You are not clear on what you're looking for in the combined plot, so you can go about that any number of ways (depending on what you want to do). Maybe the simplest example would be to use facet_grid() or facet_wrap() from ggplot2 to show them in side-by-side plots:
ggplot(newData, aes(x=name, y=value)) +
geom_col(aes(fill=gene)) +
facet_wrap(~id)

GGPlot annotation gets pushed off page scale when combining multiple plots within grid.draw

I have 5 plots for 5 different groups. I want to indicate a statistically significant difference a specific time points. I used annotate() to place asterisks in individual plots above the time points. However, when I combine all the plots together to make one figure, the asterisks get pushed off the plots. It looks like it is a problem with the y scales not being fixed. I'm providing as much data as I feel comfortable with. The first bit of code is for one of the groups. The plots all look relatively similar for the 5 groups. The second bit is the data frame I am using to combine the plots. Pictures attached of one plot by itself, then all plots combined. There should be multiple asterisks on multiple plots
ggplot(data,aes(X,Y,group=Group,color=Group))+
theme_bw()+
theme(panel.grid.major=element_line(color="white",size=.1))+
theme(panel.grid.minor=element_line(color="white",size=.1))+
geom_point(stat="summary")+
geom_errorbar(stat="summary",fun.data=mean_se,width=0.25)+
geom_line(stat="summary")+
scale_color_manual(labels = c("C", "T"),values=c("black", "red"))+
theme(axis.title.y = element_text(vjust=2.5))+
annotate("text", x=5, y=3, label= "*",size=10)
grid.newpage()
grid.draw(rbind(ggplotGrob(plotanimal1),
ggplotGrob(plotanimal2),
ggplotGrob(plotanimal3),
ggplotGrob(plotanimal4),
ggplotGrob(plotanimal5)))
You can make the asterisks by using geom_point with shape = 42. That way, ggplot will automatically fix the y axis values itself. You need to set the aesthetics at the same values you would have with annotate. So instead of
annotate("text", x=5, y=3, label= "*",size=10)
You can do
geom_point(aes(x=5, y=3), shape = 42, size = 2)
Have you tried using the package patchwork to organize the plots? It typically works better than grid.draw

Annotate is giving error in ggplot2 when using facet

I had previously used annotate() to add letters to facet panels of ggplots. After updating R (to 3.6.1), code that had previously worked with annotate no longer does.
I can solve this by making a separate dataframe to label each facet, but that is cumbersome when I have a decent number of plots to make that vary in how many facets they have. All I want is a letter (e.g., a-f) on each panel for identification in a journal article.
library(ggplot2)
data(diamonds)
ggplot(diamonds, aes(x=carat,y=price)) +geom_point()+ facet_wrap(~cut) + annotate("text",label=letters[1:5],x=4.5,y=15000,size=6,fontface="bold")
ggplot(diamonds, aes(x=carat,y=price)) +geom_point()+ facet_wrap(~cut) + annotate("text",label=letters[1],x=4.5,y=15000,size=6,fontface="bold")
The first ggplot should produce a plot that has the facets labeled with lowercase letters. Instead, I get the error:
Error: Aesthetics must be either length 1 or the same as the data (25): label
The code does work if only one letter is used, as seen in the second ggplot, so annotate will work, but not with multiple values as it previously did.
I usually always use an external data frame for faceted annotations, because it is more traceable to me.
df_labels=unique(diamonds[,"cut"])
df_labels$label=letters[as.numeric(df_labels$cut)] #to preserve factor level ordering
df_labels$x=4.5
df_labels$y=15000
ggplot(diamonds, aes(x=carat,y=price)) +
geom_point()+ facet_wrap(~cut) +
geom_text(data=df_labels,aes(x=x,y=y,label=label))

selecting only some facets to print in facet_wrap, ggplot2

my question is very simple, but I have failed to solve it after many attempts. I just want to print some facets of a facetted plot (made with facet_wrap in ggplot2), and remove the ones I am no interested in.
I have facet_wrap with ggplot2, as follows:
#anomalies linear trends
an.trends <- ggplot()+
geom_smooth(method="lm", data=tndvilong.anomalies, aes(x=year, y=NDVIan, colour=TenureZone,
group=TenureZone))+
scale_color_manual(values=miscol) +
ggtitle("anomalies' trends")
#anomalies linear trends by VEG
an.trendsVEG <- an.trends + facet_wrap(~VEG,ncol=2)
print(an.trendsVEG)
And I get the plot as I expected (you can see it in te link below):
anomalies' trends by VEG
The question is: how do I get printed only the facest I am interested on?
I only want to print "CenKal_ShWoodl", "HlShl_ShDens", "NKal_ShWoodl", and "ThShl_ShDens"
Thanks
I suggest the easiest way to do that is to simply give ggplot() an appropriate subset. In this case:
facets <- c("CenKal_ShWoodl", "HlShl_ShDens", "NKal_ShWoodl", "ThShl_ShDens")
an.trends.sub <- ggplot(tndvilong.anomalies[tndvilong.anomalies$VEG %in% facets,])+
geom_smooth(method="lm" aes(x=year, y=NDVIan, colour=TenureZone,
group=TenureZone))+
scale_color_manual(values=miscol) +
ggtitle("anomalies' trends") +
facet_wrap(~VEG,ncol=2)
Obviously without your data I can't be sure this will give you what you want, but based on your description, it should work. I find that with ggplot, it is generally best to pass it the data you want plotted, rather than finding ways of changing the plot itself.

Resources