Related
I want to create a customized legend that distinguishes two plotted geoms using appropriate shape and color. I see that guide_legend() should be involved, but my legend is presented with both shapes overlayed one on the other for both components of the legend. What is the right way to build these individual legend components using distinct shapes and colors? Thank you.
library(dplyr)
df <- tibble(year=seq(2010,2020,1),
annualNitrogen=seq(100,200,10),
annualPotassium=seq(500,600,10))
ggplot() +
geom_point(data = df, aes(x = year, y = annualNitrogen, fill="green"), shape=24, color="green", size = 4) +
geom_point(data = df, aes(x = year, y = annualPotassium, fill="blue"), color="blue", shape=21, size = 4) +
guides(fill = guide_legend(override.aes = list(color=c("green", "blue"))),
shape = guide_legend(override.aes = list(shape=c(21, 24)))
) +
scale_fill_manual(name = 'cumulative\nmaterial',
values = c("blue"="blue" , "green"="green" ),
labels = c("potassium" , "nitrogen") ) +
theme_bw() +
theme(legend.position="bottom")
Here it helps to transform to "long" format which is more in line with how ggplot is designed to be used when separating factor levels within a single time series.
This allows us to map shape and color directly, rather than having to manually assign different values to multiple plotted series, like you do in your question.
library(tidyverse)
df %>%
pivot_longer(-year, names_to = "element") %>%
ggplot(aes(x=year, y = value, fill = element, shape = element, color = element)) +
geom_point(size = 4)+
scale_color_manual(values = c("green", "blue"))
Put your df into a long format that ggplot likes with tidyr::gather. You should only use one geom_point for this, you don't need separate geoms for separate variables. You can then specify the shape and variable in one call to geom_point.
df <- tibble(year=seq(2010,2020,1),
annualNitrogen=seq(100,200,10),
annualPotassium=seq(500,600,10))
df <- tidyr::gather(df, key = 'variable', value='value', annualNitrogen, annualPotassium)
ggplot(df) +
geom_point(aes(x = year, y = value, shape = variable, color = variable)) +
scale_color_manual(
name = 'cumulative\nmaterial',
values = c(
"annualPotassium" = "blue",
"annualNitrogen" = "green"),
labels = c("potassium" , "nitrogen")) +
guides(shape = FALSE)
I came across this question the other day and tried to re-create it for myself. ggplot, facet, piechart: placing text in the middle of pie chart slices
. My data is in a very similar format, but sadly the accepted answer did not help, hence why I am re posting.
I essentially want to create the accepted answer but with my own data, yet the issue I run into is that coord_polar does not support free scale. Using the first answer:
I tried it using the second version of the answer, with the ddplyr version, but I also do not get my desired output. Using the second answer:
Clearly none of these has the desired effect. I would prefer to create one as with size pie charts, but only showed four as an example, follows: .
This I did in excel, but with one legend, and no background grid.
Code
title<-c(1,1,2,2,3,3,4,4,5,5,6,6)
type<-c('A','B','A','B','A','B','A','B','A','B','A','B')
value<-c(0.25,0.75,0.3,0.7,0.4,0.6,0.5,0.5,0.1,0.9,0.15,0.85)
piec<-data.frame(title,type,value)
library(tidyverse)
p1<-ggplot(data = piec, aes(x = "", y = value, fill = type)) +
geom_bar(stat = "identity") +
geom_text(aes(label = value), position = position_stack(vjust = 0.5)) +
coord_polar(theta = "y")
#facet_grid(title ~ ., scales = "free")
p1
piec <- piec %>% group_by(title) %>% mutate(pos=cumsum(value)-0.5*value)
p2<-ggplot(data = piec) +
geom_bar(aes(x = "", y = value, fill = type), stat = "identity") +
geom_text(aes(x = "", y = pos, label = value)) +
coord_polar(theta = "y")
#facet_grid(Channel ~ ., scales = "free")
p2
You don't have to supply different y values for geom_text and geom_bar (use y = value for both of them). Next you have to specify position in geom_text. Finally, remove scales from facets.
library(ggplot2)
title<-c(1,1,2,2,3,3,4,4,5,5,6,6)
type<-c('A','B','A','B','A','B','A','B','A','B','A','B')
value<-c(0.25,0.75,0.3,0.7,0.4,0.6,0.5,0.5,0.1,0.9,0.15,0.85)
piec<-data.frame(title,type,value)
ggplot(piec, aes("", value, fill = type)) +
geom_bar(stat = "identity", color = "white", size = 1) +
geom_text(aes(label = paste0(value * 100, "%")),
position = position_stack(vjust = 0.5),
color = "white", size = 3) +
coord_polar(theta = "y") +
facet_wrap(~ title, ncol = 3) +
scale_fill_manual(values = c("#0048cc", "#cc8400")) +
theme_void()
A very similar question to the one asked here. However, in that situation the fill parameter for the two plots are different. For my situation the fill parameter is the same for both plots, but I want different color schemes.
I would like to manually change the color in the boxplots and the scatter plots (for example making the boxes white and the points colored).
Example:
require(dplyr)
require(ggplot2)
n<-4*3*10
myvalues<- rexp((n))
days <- ntile(rexp(n),4)
doses <- ntile(rexp(n), 3)
test <- data.frame(values =myvalues,
day = factor(days, levels = unique(days)),
dose = factor(doses, levels = unique(doses)))
p<- ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot( aes(fill = dose))+
geom_point( aes(fill = dose), alpha = 0.4,
position = position_jitterdodge())
produces a plot like this:
Using 'scale_fill_manual()' overwrites the aesthetic on both the boxplot and the scatterplot.
I have found a hack by adding 'colour' to geom_point and then when I use scale_fill_manual() the scatter point colors are not changed:
p<- ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot(aes(fill = dose), outlier.shape = NA)+
geom_point(aes(fill = dose, colour = factor(test$dose)),
position = position_jitterdodge(jitter.width = 0.1))+
scale_fill_manual(values = c('white', 'white', 'white'))
Are there more efficient ways of getting the same result?
You can use group to set the different boxplots. No need to set the fill and then overwrite it:
ggplot(data = test, aes(x = day, y = values)) +
geom_boxplot(aes(group = interaction(day, dose)), outlier.shape = NA)+
geom_point(aes(fill = dose, colour = dose),
position = position_jitterdodge(jitter.width = 0.1))
And you should never use data$column inside aes - just use the bare column. Using data$column will work in simple cases, but will break whenever there are stat layers or facets.
I want to change the order of the bar plot only for the last set, just to highlight it. I used scale_fill_manual(), but it didn't help much.
Here's my code:
x<-c(rep(c("Type1", "Type2"),4))
y<-c(4,5,6,7,3,4,5,2)
time<-c(2010,2010,2011,2011,2012,2012,2013,2013)
z<-data.frame(type = x, val=y, Time = time)
ggplot(data = z, aes(x=Time,y=val)) +
geom_bar(stat = "identity", position = "dodge", aes(fill=type))+
scale_fill_manual(values = c(rep(c("white", "gray51"),3),"white","red"))
Here's the output:
I want the graph to look like:
Is there any way I can do this? I would appreciate any help. I looked at change color of only one bar in ggplot but it doesn't seem to be about grouped data.
My general mantra is that ggplot is very good at plotting the data you give it. If you want it to plot something different, the easiest way is usually to modify your data.
z$type2 = as.character(z$type)
z$type2[z$type == "Type2" & z$Time == 2013] = "Type2 "
I added a sneaky extra space in "Type2 " for the row you want to highlight. It will be a distinct factor level and get its own color (and even be coerced into the a nice order using the alphabetical default). But it will appear the same in the legend label.
ggplot(data = z, aes(x=Time,y=val)) +
geom_bar(stat = "identity", position = "dodge", aes(fill=type2))+
scale_fill_manual(values = c("white", "gray50", "red"))
I thought that omitting the red from the legend would be difficult, but this answer showed me that all that is needed is to add breaks = c("Type1", "Type2") as an argument to scale_fill_manual.
What about highlighting the bar with a border. For example:
z$hi = with(z, ifelse(type=="Type2" & Time==2013, "Y","N"))
ggplot(data = z, aes(x=Time,y=val)) +
geom_bar(stat = "identity", position = "dodge",
aes(fill=type, colour=hi), size=1) +
scale_fill_manual(values=c("gray51","white")) +
scale_colour_manual(values=c(NA,"red")) +
guides(colour=FALSE)
UPDATE: In response to your comment: I think a line plot makes it easier to see the trends and the relationships between each type. For example:
ggplot(data = z, aes(x=Time,y=val,colour=type)) +
geom_line() +
geom_point() +
geom_point(data=z[z$hi=="Y",], aes(x=Time, y=val), size=4, pch=1,
colour=hcl(195,100,40), stroke=1) +
scale_y_continuous(limits=c(0,max(z$val))) +
theme_bw()
Easy to do it with the legend, though you may want to be cautious about throwing users off with the abrupt change in color. Simply add an additional category to your x variable to indicate where you want the highlighting.
x<- xHigh <- c(rep(c("Type1", "Type2"),4))
xHigh[length(xHigh)] <- "Type2_highlight"
myHighlight <- rep("No",length(x))
myHighlight[length(myHighlight)] <- "Yes"
y<-c(4,5,6,7,3,4,5,2)
time<-c(2010,2010,2011,2011,2012,2012,2013,2013)
z<-data.frame(type = x, xHigh = xHigh, val=y, Time = time, myHighlight = myHighlight)
ggplot(data = z, aes(x=Time,y=val)) +
geom_bar(stat = "identity", position = "dodge", aes(fill=xHigh))+
scale_fill_manual(values = c(Type1 = "white", Type2 = "gray51", Type2_highlight = "red"))
Another potential option for highlighting a particular bar is to draw a box around it, like so:
ggplot(data = z, aes(x=Time,y=val)) +
geom_bar(stat = "identity", position = "dodge", aes(fill=type))+
scale_fill_manual(values = c(Type1 = "white", Type2 = "gray51")) +
geom_bar(aes(linetype = xHigh)
, fill = NA
, stat = "identity", position = "dodge"
, col = "red"
, show.legend = FALSE) +
scale_linetype_manual(values = c(Type1 = 0
, Type2 = 0
, Type2_highlight = 1))
Hope that helps.
How can I can remove the letter 'a' from the legend generated by this code? If I remove the geom_text, then the 'a' letter will not show in the legend. I want to keep geom_text, though.
ggplot(data = iris, aes(x = Sepal.Length, y=Sepal.Width,
shape = Species, colour = Species)) +
geom_point() +
geom_text(aes(label = Species))
Set show.legend = FALSE in geom_text:
ggplot(data = iris,
aes(x = Sepal.Length, y = Sepal.Width, colour = Species,
shape = Species, label = Species)) +
geom_point() +
geom_text(show.legend = FALSE)
The argument show_guide changed name to show.legend in ggplot2 2.0.0 (see release news).
Pre-ggplot2 2.0.0:
With show_guide = FALSE like so...
ggplot(data = iris, aes(x = Sepal.Length, y = Sepal.Width , colour = Species,
shape = Species, label = Species ), size = 20) +
geom_point() +
geom_text(show_guide = FALSE)
We can use guide_legend(override.aes = aes(...)) to hide the 'a' in the legend.
Below is a short example of how you might use guide_legend()
library(ggrepel)
#> Loading required package: ggplot2
d <- mtcars[c(1:8),]
p <- ggplot(d, aes(wt, mpg)) +
geom_point() +
theme_classic(base_size = 18) +
geom_label_repel(
aes(label = rownames(d), fill = factor(cyl)),
size = 5, color = "white"
)
# Let's see what the default legend looks like.
p
# Now let's override some of the aesthetics:
p + guides(
fill = guide_legend(
title = "Legend Title",
override.aes = aes(label = "")
)
)
Created on 2019-04-29 by the reprex package (v0.2.1)
I had a similar problem. Simon's solution worked for me but a slight twist was required. I did not realise that I need to add "show_guide = F" to geom_text's arguments, rather than replace with it the existing arguments - which is what Simon's solution shows. For a ggplot2 noob like me this was not that obvious. A proper example would have used the OP's code and just added the missing argument like this:
..
geom_text(aes(label=Species), show_guide = F) +
..
Like Nick said
the following code would still produce the error:
geom_text(aes(x=1,y=2,label="",show_guide=F))
whereas:
geom_text(aes(x=1,y=2,label=""),show_guide=F)
outside the aes argument eliminates the a over the legend
I had a similar problem, with an 'a' appearing behind different coloured points I was trying to label with geom_text_repel. To remove the 'a', so that it would just show the point without the 'a' behind it, I had to add show.legend=FALSE as an argument in geom_text_repel.
Hope that makes sense to anyone who might be labouring with the same issue!
You can also use show.legend = FALSE in the arguments of geom_label_repel() to remove the "a" in the legend.
So, instead of
ggplot(d, aes(wt, mpg)) +
geom_point() +
theme_classic(base_size = 18) +
geom_label_repel(
aes(label = rownames(d), fill = factor(cyl)),
size = 5, color = "white"
)+ guides(
fill = guide_legend(
title = "Legend Title",
override.aes = aes(label = "")
)
)
you can do,
ggplot(d, aes(wt, mpg)) +
geom_point() +
theme_classic(base_size = 18) +
geom_label_repel(
aes(label = rownames(d), fill = factor(cyl)),
size = 5, color = "white",
show.legend = FALSE )