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")
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)
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:
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?
I am trying to arrange the bars in this stem plot from longest to shortest. This https://www.r-graph-gallery.com/301-custom-lollipop-chart/ suggests that i can use the arrange function before I pipe into the graph. I can't reproduce their example. The bars end up in a sort of random order. Any idea why the arrange is not working
mtcars %>%
mutate(mpg = as.numeric(mpg)) %>%
mutate(x = factor(rownames( mtcars))) %>%
arrange(mpg) %>%
ggplot( aes(x=x, y=mpg)) +
geom_segment( aes(x=x, xend=x, y=0, yend=mpg), color="skyblue", size=1) +
geom_point( color="blue", size=4, alpha=0.6) +
theme_light() +
coord_flip()
I'm writing this answer quickly on my phone so forgive me for not having testable code, but you need to change the order of the factor rather rather arranging the data frame.
Maybe if you arrange by mpg before creating your x variable.
mtcars %>%
mutate(mpg = as.numeric(mpg)) %>%
arrange(mpg) %>%
mutate(x = factor(rownames( mtcars), levels = rownames( mtcars))) %>%
ggplot( aes(x=x, y=mpg)) +
geom_segment( aes(x=x, xend=x, y=0, yend=mpg), color="skyblue", size=1) +
geom_point( color="blue", size=4, alpha=0.6) +
theme_light() +
coord_flip()
I would like to create a ggplot facet grid where the x axis of the grid (not the plot) are the labels, rather than squish into each chartlet.
Example:
mtcars %>%
group_by(mpg) %>%
mutate(cnt = n()) %>%
ggplot(aes(x = cyl, y = cnt)) +
geom_bar(stat = "identity") +
facet_grid(vs ~ cyl)
Looks like:
Rather than having 3 through 9 on each individual chart, I would like the horizontal part of the grid to be cyl as opposed to each individual chart.
In other words, each bar chart should be a single column bar chart only.
How can I do this?
Use a constant for the x value, while still faceting by cyl:
library(tidyverse)
mtcars %>%
group_by(mpg) %>%
mutate(cnt = n()) %>%
ggplot(aes(x = 1, y = cnt)) +
geom_bar(stat = "identity") +
facet_grid(vs ~ cyl) +
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank()) +
labs(x = "cyl")
Like this?
mtcars %>%
group_by(mpg) %>%
mutate(cnt = n()) %>%
ggplot(aes(x = cyl, y = cnt)) +
geom_bar(stat = "identity") +
facet_grid(vs ~ cyl)+
theme(axis.text.x = element_blank(),axis.ticks = element_blank())
Or like this?
mtcars %>%
group_by(mpg) %>%
mutate(cnt = n()) %>%
ggplot(aes(x = cyl, y = cnt)) +
geom_bar(stat = "identity") +
facet_grid(vs ~ cyl, scales="free")+
theme(axis.text.x = element_blank(),axis.ticks = element_blank())