I have a facet plot in R and I want to give a subtitle to the different columns and the different rows of the plot.
I created an example based on the mpg data.
library(ggplot2)
p <- ggplot(mpg, aes(displ, cty)) + geom_point()
p + facet_grid(drv ~ cyl) +
scale_y_continuous("cty",
sec.axis = sec_axis(~., breaks=NULL, name = "drv")) +
ggtitle("plot from mpg", subtitle="cyl")
This already does what I want. The label on the bottom describes the x-axis on each of the little plots. The label on the top describes what the 4 columns represent. The label on the left describes the y-axis on the little plots and the label on the right describes the rows of the plot.
However, I kind of cheated. The label on the top is actually a subtitle of the plot and the label on the right is created through a secondary axis. I had to put breaks=NULL to hide the secondary axis and just display its name. This also creates lots of warning messages.
Is there a proper way with facet_grid to do what I want?
Edit: I noticed that my code example was incomplete and not functional. I corrected it, hopefully it works now.
Related
I plotted a grouped boxplot and trying to change the background color for each panel. I can use panel.background function to change whole plot background. But how this can be done for individual panel? I found a similar question here. But I failed to adopt the code to my plot.
Top few lines of my input data look like
Code
p<-ggplot(df, aes(x=Genotype, y=Length, fill=Treatment)) + scale_fill_manual(values=c("#69b3a2", "#CF7737"))+
geom_boxplot(width=2.5)+ theme(text = element_text(size=20),panel.spacing.x=unit(0.4, "lines"),
axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank(),axis.text.y = element_text(angle=90, hjust=1,colour="black")) +
labs(x = "Genotype", y = "Petal length (cm)")+
facet_grid(~divide,scales = "free", space = "free")
p+theme(panel.background = element_rect(fill = "#F6F8F9", colour = "#E7ECF1"))
Unfortunately, like the other theme elements, the fill aesthetic of element_rect() cannot be mapped to data. You cannot just send a vector of colors to fill either (create your own mapping of sorts). In the end, the simplest solution probably is going to be very similar to the answer you linked to in your question... with a bit of a twist here.
I'll use mtcars as an example. Note that I'm converting some of the continuous variables in the dataset to factors so that we can create some more discrete values.
It's important to note, the rect geom is drawn before the boxplot geom, to ensure the boxplot appears on top of the rect.
ggplot(mtcars, aes(factor(carb), disp)) +
geom_rect(
aes(fill=factor(carb)), alpha=0.5,
xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
geom_boxplot() +
facet_grid(~factor(carb), scales='free_x') +
theme_bw()
All done... but not quite. Something is wrong and you might notice this if you pay attention to the boxes on the legend and the gridlines in the plot panels. It looks like the alpha value is incorrect for some facets and okay for others. What's going on here?
Well, this has to do with how geom_rect works. It's drawing a box on each plot panel, but just like the other geoms, it's mapped to the data. Even though the x and y aesthetics for the geom_rect are actually not used to draw the rectangle, they are used to indicate how many of each rectangle are drawn. This means that the number of rectangles drawn in each facet corresponds to the number of lines in the dataset which exist for that facet. If 3 observations exist, 3 rectangles are drawn. If 20 observations exist for one facet, 20 rectangles are drawn, etc.
So, the fix is to supply a dataframe that contains one observation each for every facet. We have to then make sure that we supply any and all other aesthetics (x and y here) that are included in the ggplot call, or we will get an error indicating ggplot cannot "find" that particular column. Remember, even if geom_rect doesn't use these for drawing, they are used to determine how many observations exist (and therefore how many to draw).
rect_df <- data.frame(carb=unique(mtcars$carb)) # supply one of each type of carb
# have to give something to disp
rect_df$disp <- 0
ggplot(mtcars, aes(factor(carb), disp)) +
geom_rect(
data=rect_df,
aes(fill=factor(carb)), alpha=0.5,
xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf) +
geom_boxplot() +
facet_grid(~factor(carb), scales='free_x') +
theme_bw()
That's better.
I'm trying to make a plot with five separate lines that represent different variables (i.e., columns). I've been trying to fix the legend and I can't get it right. The colors also seem to be incorrect, so I'm confused as to how to proceed. Data, code, and current plot are below:
test.dat <- data.frame(matrix(c(0,.072,.063,.062,.059,.055,1,.029,.035,.024,.036,.017),
nrow=2,byrow=T))
colnames(test.dat) <- c("X1","Y1","Y2","Y3","Y4","Y5")
test.plot <- ggplot(data=test.dat) +
geom_line(aes(x=X1, y=Y1, color="darkred")) +
geom_line(aes(x=X1, y=Y2, color="darkgreen")) +
geom_line(aes(x=X1, y=Y3, color="darkblue")) +
geom_line(aes(x=X1, y=Y4, color="darkorange")) +
geom_line(aes(x=X1, y=Y5, color="darkgoldenrod"))
I'm trying to make the variable names (i.e., Y1, Y2, etc.) the names for the lines on the legend as well as name the legend itself. I've googled around to figure out how to change the legend, but nothing I've tried changes the plot. I also need to fix the the axis labels and add a plot title.
I'm fairly new to ggplot, so a point in the right direction would be much appreciated. Please let me know if I can clarify anything.
It is easier if you change your data from wide to long, and then plot the lines. You are also defining the colors within the aes() parameter which does not change the color, but, in effect, creates a variable with that value.
You did not mention exactly what you want to do with your axis labels, but they can be edited using scale_x_continuous or scale_y_continuous
library(tidyverse)
test.dat <- data.frame(matrix(c(0,.072,.063,.062,.059,.055,1,.029,.035,.024,.036,.017),
nrow=2,byrow=T))
colnames(test.dat) <- c("X1","Y1","Y2","Y3","Y4","Y5")
test.dat %>%
gather(Y_var, value, -X1) %>%
ggplot(aes(x = X1, y = value, color = Y_var)) +
geom_line() +
scale_color_manual(
values = c("darkred","darkgreen","darkblue","darkorange",
"darkgoldenrod")
) +
labs(title = "Some plot title",
color = "Some legend title")
How can I produce a plot with two legends where one legend is vertical and the other legend is horizontal?
Using the iris data set, here is an example:
ggplot(iris,aes(x=Sepal.Width,y=Petal.Width,color=Species,size=Sepal.Length))+
geom_point() +
scale_size_continuous(breaks=c(seq(from=5,to=7,by=0.4))) +
facet_wrap(~Species,ncol = 2) +
theme(legend.position=c(.7,.2))
I would like to have the Species color legend remain vertical but have the Sepal.Length legend be horizontal below it. Is this possible?
Note: I understand that the faceting makes the color legend unnecessary. I am simply using this as an example.
You can control the features of particular legends using the guides interface.
ggplot(iris,aes(x=Sepal.Width,y=Petal.Width,color=Species,size=Sepal.Length))+
geom_point() +
scale_size_continuous(breaks=c(seq(from=5,to=7,by=0.4))) +
guides(size=guide_legend(direction='horizontal')) +
facet_wrap(~Species,ncol = 2) +
theme(legend.position=c(.7,.2))
When trying to plot something like this:
library(ggplot2)
d <- ggplot(diamonds, aes(carat, price)) +
xlim(0, 2) + geom_point()
d + facet_wrap(~ color)
You will notice that the x-axis labels only show up for the first column. I would like them to repeate on the second and third column. Is this possible?
If on the facet_wrap I use the option scales="free",
d + facet_wrap(~ color, scales="free")
then i get x-axis labels on all plots, which I also don't want. I want only labels in the bottom row repeating across columns
If the number of panels to be plot is such, that all columns have the same number of plots, the axis gets repeated in the way I want. But I can't always have the right number of panels for that.
With version 2.2.0 of ggplot this problem is fixed.
see https://www.rstats-tips.net/2016/11/ggplot2-x-axis-scale-now-available-on-all-facet-columns/
Maybe it's because of the dark outside, but I can't get this
Position geom_text on dodged barplot
to work on my fairly simple dataframe
fs <- data.frame(productcategory=c("c2","c2"), product=c("p4", "p5"), ms1=c(2,1))
plot <- ggplot(data=NULL)
plot +
geom_bar(data=fs, aes(x=productcategory, y=ms1, weight=ms1, fill=product),stat="identity", position="dodge") +
geom_text(data=fs, aes(label = ms1, x = productcategory, y=ms1+0.2), position=position_dodge(width=1)))
My plot still shows the labels in the "middle" of the product category and not above of the proper product.
Looks like this even it seems very simple, but I'm totally stuck on this
So any hints are very much appreciated how to get labels above the proper bars.
Tom
Because you have the aesthetics defined for each geom individually, geom_text isn't picking up on the fact that you're subdividing the x variable productcategory by the fill variable product.
You can get the graph you want by adding fill=product to the aes() call for geom_text, or you can try to define as many aesthetics as possible in the original ggplot() call, so that all the geoms pick up on those aesthetics automatically and you only have to define them if they're specific to that particular geom.
plot2 <- ggplot(data=fs, aes(x=productcategory, y=ms1, fill=product)) +
geom_bar(stat="identity", position="dodge") +
geom_text(aes(label=ms1, y =ms1 + 0.2), position=position_dodge(width=1))
print(plot2)