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))
Related
I want to overlay two sets of ggplot panels (each panel is a different country) into one, single ggplot panel, without any rescaling of any of the two plots, but ggplot rescales either one or the other.
I have tried using only one ggplot to include both variables, by doing ggplot(df, aes(x=t, y=a)), and, within that ggplot, then using geom_point and geom_smooth for the second variable (y=b), but this rescales variable a.
# plot 1
g <-ggplot(df, aes(x=year, y=a))
p <-g + geom_point(alpha=0.7) + geom_smooth(method="auto") + facet_wrap(~country, scales="free") + theme_bw() +
xlab("Year") + ylab(bquote('a')) +
scale_x_continuous(breaks=seq(1960, 2020, 15))
# plot 2
a <-ggplot(df, aes(x=year, y=b))
b <-a + geom_point(alpha=0.7, color="green") + geom_smooth(method="auto", color="darkgreen") +
facet_wrap(~country, scales="free") + theme_bw() +
xlab("Year") + ylab(bquote('b')) +
scale_x_continuous(breaks=seq(1960, 2020, 15))
I expect to be able to overlay these two ggplots into a single set of panels, with both y-axes appearing exactly as they appear when they're plotted alone (including units). I would then need to somehow make one of the y-axis appear to the right of the panels, so I have two y-axes, one at each side.
Image 1. ggplot rescales left y-axis. I don't want this to happen.
Image 2. What I want instead is to be able to somehow merge each of these images to get a single panel per country, displaying both the green and the blue lines with the scales that appear here.
I am trying to change the style settings of this kind of chart and hope you can help me.
R code:
set_theme(theme_bw)
cglac$pred2<-as.factor(cglac$pred)
ggplot(cglac, aes(x=depth, colour=pred2))
+ geom_bar(aes(y=..density..),binwidth=3, alpha=.5, position="stack")
+ geom_density(alpha=.2)
+ xlab("Depth (m)")
+ ylab("Counts & Density")
+ coord_flip()
+ scale_x_reverse()
+ theme_bw()
which produces this graph:
Here some points:
What I want is to have the density line as black and white lines separated by symbols rather than colour (dashed line, dotted line etc).
The other thing is the histogram itself. How do I get rid of the grey background in the bars?
Can I change the bars also to black and white symbol lines (shaded etc)? So that they would match the density lines?
Last but not least I want to add a second x or in this case y axis, because of flip_coord(). The one I see right now is for the density. The other one I need would then be the count data from the pred2 variable.
Thanks for helping.
Best,
Moritz
Have different line types: inside aes(), put linetype = pred2. To make the line color black, inside geom_density, add an argument color = "black".
The "background" of the bars is called "fill". Inside geom_bar, you can set fill = NA for no fill. A more common approach is to fill in the bars with the colors, inside aes() specify fill = pred2. You might consider faceting by your variable, + facet_wrap(~ pred2, nrow = 1) might look very nice.
Shaded bars in ggplot? No, you can't do that easily. See the answers to this question for other options and hacks.
Second y-axis, similar to the shaded symbol lines, the ggplot creator thinks a second y-axis is a terrible design choice, so you can't do it at all easily. Here's a related question, including Hadley's point of view:
I believe plots with separate y scales (not y-scales that are transformations of each other) are fundamentally flawed.
It's definitely worth considering his point of view, and asking yourself if those design choices are really what you want.
Different linetypes for densities
Here's my built-in data version of what you're trying to do:
ggplot(mtcars, aes(x = hp,
linetype = cyl,
group = cyl,
color = cyl)) +
geom_histogram(aes(y=..density.., fill = cyl),
alpha=.5, position="stack") +
geom_density(color = "black") +
coord_flip() +
theme_bw()
And what I think you should do instead. This version uses facets instead of stacking/colors/linetypes. You seem to be aiming for black and white, which isn't a problem at all in this version.
ggplot(mtcars, aes(x = hp,
group = cyl)) +
geom_histogram(aes(y=..density..),
alpha=.5) +
geom_density() +
facet_wrap(~ cyl, nrow = 1) +
coord_flip() +
theme_bw()
I am new to ggplot, and using ggplot to show box plots of my data corresponding to different types like this. There are four types. I found that I can use facet_wrap to generate four different graphs.
ggplot(o.xp.sample, aes(power, reduction, fill=interaction(type,power), dodge=type)) +
stat_boxplot(geom ='errorbar')+
geom_boxplot() +
facet_wrap(~type)
My question is, I want to combine all the four graphs into one graph such that each type has a different color (and slightly transparent to show other plots through). Is this possible?
Here is the data https://gist.github.com/anonymous/9589729
Try this:
library(ggplot2)
o.xp.sample = read.csv("C:\\...\\data.csv",sep=",")
ggplot(o.xp.sample, aes(factor(power), reduction, fill=interaction(type,power), dodge=type)) +
stat_boxplot(geom ='errorbar') +
geom_boxplot() +
theme_bw() +
guides(fill = guide_legend(ncol = 3)) #added line as suggested by Paulo Cardoso
I'm plotting lines with ggplot2 like this:
ggplot(iris, aes(Petal.Width,Petal.Length,color=Species)) + geom_line() + theme_bw()
.
I find legend marks to be small so I want them to be bigger. If I change the size, lines on the plot change too:
ggplot(iris, aes(Petal.Width,Petal.Length,color=Species)) + geom_line(size=4) + theme_bw()
.
But I only want to see thick lines in the legend, I want lines on the plot to be thin. I tried to use legend.key.size but it changes the square of the mark, not the width of the line:
library(grid) # for unit
ggplot(iris,aes(Petal.Width,Petal.Length,color=Species))+geom_line()+theme_bw() + theme(legend.key.size=unit(1,"cm"))
I also tried to use points:
ggplot(iris,aes(Petal.Width,Petal.Length,color=Species)) + geom_line() + geom_point(size=4) + theme_bw()
But of course it still affects both plot and legend:
I wanted to use lines for the plot and dots/points for the legend.
So I'm asking about two things:
How to change width of line in the legend without changing the plot?
How to draw lines in the plot, but draw points/dots/squares in the legend?
To change line width only in the legend you should use function guides() and then for colour= use guide_legend() with override.aes= and set size=. This will override size used in plot and will use new size value just for legend.
ggplot(iris,aes(Petal.Width,Petal.Length,color=Species))+geom_line()+theme_bw()+
guides(colour = guide_legend(override.aes = list(size=3)))
To get points in legend and lines in plot workaround would be add geom_point(size=0) to ensure that points are invisible and then in guides() set linetype=0 to remove lines and size=3 to get larger points.
ggplot(iris,aes(Petal.Width,Petal.Length,color=Species))+geom_line()+theme_bw()+
geom_point(size=0)+
guides(colour = guide_legend(override.aes = list(size=3,linetype=0)))
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)