I can specify the colors in a plot by using scale_color_manual as below:
library(tidyverse)
mpg %>%
filter(class=="2seater"|class=="minivan")%>%
ggplot(aes(displ, hwy,colour=class)) +
geom_point()+
scale_color_manual(values=c(
"2seater"="green",
"minivan"="red"))
But if I had a separate dataframe as below:
class<-c("2seater","minivan")
color<-c("green","red")
colorscheme<-data.frame(class,color,stringsAsFactors = FALSE)
How can I use this to specify the colors within the ggplot?
mpg %>%
filter(class %in% c("2seater", "minivan")) %>%
ggplot(aes(displ, hwy, color = class)) +
geom_point() +
scale_color_manual(values = colorscheme$color,
labels = colorscheme$class)
Another option can be scale_color_identity() after joining:
library(tidyverse)
#Code
mpg%>%filter(class=="2seater"|class=="minivan")%>%
left_join(colorscheme) %>%
ggplot(aes(displ, hwy,colour=color)) +
geom_point()+
scale_color_identity(guide = "legend",
labels=c("2seater","minivan"),name='class')
Output:
Related
I would like to reverse the order of the legend for a horizontal bar chart. When adding guides(fill = guide_legend(reverse = TRUE)) to the ggplot it works fine (see second plot). However, after applying ggplotly() the legend is again in the default order.
How to reverse the order of the plotly legend without changing the order of the bars?
library(ggplot2)
library(dplyr)
data(mtcars)
p1 <- mtcars %>%
count(cyl, am) %>%
mutate(cyl = factor(cyl), am = factor(am)) %>%
ggplot(aes(cyl, n, fill = am)) +
geom_col(position = "dodge") +
coord_flip()
p1
p2 <- p1 + guides(fill = guide_legend(reverse = TRUE))
p2
plotly::ggplotly(p2)
Adding to the great answer of #Zac Garland here is a solution that works with legends of arbitrary length:
library(ggplot2)
library(dplyr)
reverse_legend_labels <- function(plotly_plot) {
n_labels <- length(plotly_plot$x$data)
plotly_plot$x$data[1:n_labels] <- plotly_plot$x$data[n_labels:1]
plotly_plot
}
p1 <- mtcars %>%
count(cyl, am) %>%
mutate(cyl = factor(cyl), am = factor(am)) %>%
ggplot(aes(cyl, n, fill = am)) +
geom_col(position = "dodge") +
coord_flip()
p2 <- mtcars %>%
count(am, cyl) %>%
mutate(cyl = factor(cyl), am = factor(am)) %>%
ggplot(aes(am, n, fill = cyl)) +
geom_col(position = "dodge") +
coord_flip()
p1 %>%
plotly::ggplotly() %>%
reverse_legend_labels()
p2 %>%
plotly::ggplotly() %>%
reverse_legend_labels()
When you call ggplotly, it's really just creating a list and a function call on that list.
So if you save that intermediate step, you can modify the list directly. and as such, modify the plot output.
library(ggplot2)
library(dplyr)
data(mtcars)
p1 <- mtcars %>%
count(cyl, am) %>%
mutate(cyl = factor(cyl), am = factor(am)) %>%
ggplot(aes(cyl, n, fill = am)) +
geom_col(position = "dodge") +
coord_flip()
html_plot <- ggplotly(p1)
replace_1 <- html_plot[["x"]][["data"]][[2]]
replace_2 <- html_plot[["x"]][["data"]][[1]]
html_plot[["x"]][["data"]][[1]] <- replace_1
html_plot[["x"]][["data"]][[2]] <- replace_2
html_plot
plot output
A simple solution is to define the order of the levels of the factor variable am:
library(ggplot2)
library(dplyr)
data(mtcars)
df <- mtcars %>%
count(cyl, am) %>%
mutate(cyl = factor(cyl), am = factor(as.character(am), levels = c("1", "0")))
head(df)
p1 <- df %>%
ggplot(aes(cyl, n, fill = am)) +
geom_col(position = "dodge") +
coord_flip()
p1
plotly::ggplotly(p1)
library(dplyr)
#Code
mpg %>%
mutate(Color=ifelse(class=='2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point()
In the above code if i would like to separately label 2 wheeler on top of the blue dots for 2 wheeler instead of a separate column for legends, what would be the modification for my code pls?
Not sure if I understand you correctly, but does this answer your question?
library(ggplot2)
library(dplyr)
#install.packages("ggrepel")
library(ggrepel)
#Code
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = ifelse(Color == '2seater', '2seater', "")),
ylim = 35, force_pull = 0, show.legend = FALSE)
Or perhaps this?
library(ggplot2)
library(dplyr)
#install.packages("ggrepel")
library(ggrepel)
#Code
mpg %>%
mutate(Color=ifelse(class == '2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point() +
geom_text_repel(aes(label = ifelse(Color == '2seater', '2seater', "")),
force_pull = 0, show.legend = FALSE) +
theme(legend.position = "none")
Or some combination of the two?
library(ggplot2)
ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point()
If I want to colour a particular class, let us say 2 seater, what is the modification in the code
Try this. You can wrap the logical condition directly inside colour element:
library(ggplot2)
ggplot(mpg, aes(displ, hwy, colour = (class=='2seater'))) +
geom_point()+
labs(color='class')+
scale_color_discrete(labels=c('TRUE'='2seater','FALSE'='other'))
Output:
As legend will not have a fashion title, you can use labs() to change that or follow the pretty smart advice from #r2evans creating a new column to store the results of the logical condition using dplyr:
library(dplyr)
#Code
mpg %>%
mutate(Color=ifelse(class=='2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point()
Output:
Update:
#Code2
mpg %>% mutate(Color=ifelse(class=='2seater','2seater','Other')) %>%
ggplot(aes(displ, hwy, colour = Color)) +
geom_point()+
scale_color_manual(values = c("2seater" = "#992399", "Other" = "#000000"))+
geom_smooth(method = 'lm',aes(group=1),show.legend = F)
Output:
You can try adding specific colors this way too:
ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
scale_color_manual(values = c("2seater" = "#992399", "Other" = "#000000"))
I want to sort the boxplots by the x-axis-values (hwy here) within every facet (class here). I tried 2 methods, but failed:
library(tidyverse); library(forcats)
mpg %>%
ggplot(aes(x = hwy, y = fct_reorder(trans, hwy, median))) +
geom_boxplot() +
facet_wrap(~class, scales = "free_y")
mpg %>%
group_by(class) %>%
mutate(trans = fct_reorder(trans, hwy, median)) %>%
ungroup() %>%
ggplot(aes(x = hwy, y = trans)) +
geom_boxplot() +
facet_wrap(~class, scales = "free_y")
What am I missing here?
Thanks Tung, that link gave me the clue! The function reorder_within from the tidytext was useful here:
mpg %>%
ggplot(aes(x = hwy, y = tidytext::reorder_within(trans, hwy, class, median))) +
geom_boxplot() +
facet_wrap(~class, scales = "free_y")
...but the only problem now is the text _class got attached to every y-value on the chart? Is there a way to fix that?
Is it possible to create multiple ggplots using facet_wrap when having y varaible always the same and just changing x variable:
Lets say we have:
library(ggplot2)
library(dplyr)
colnames(mtcars)
mtcars %>%
ggplot(aes(hp, mpg)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, cyl)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, disp)) +
geom_point() +
geom_smooth(method = "lm")
mtcars %>%
ggplot(aes(hp, drat)) +
geom_point() +
geom_smooth(method = "lm")
.
.
.
mtcars %>%
ggplot(aes(hp, carb)) +
geom_point() +
geom_smooth(method = "lm")
I know plots above can be create manually and then using grid arrange combined, however is there more efficient way?
With a little data augmentation, we can. We first create an "id" using row_number, and then use the gather function to go from a wide data set into a tall data set. We deselect the id and hp columns.
mtcars %>%
mutate(id = row_number()) %>%
gather(variable, value, -id, -hp) %>%
ggplot(aes(hp, value))+
geom_point()+
geom_smooth(method = "lm")+
facet_wrap(~variable, scales = "free_y")