I refer to section 12.2.4, exercise 1 in Hadley Wickham's ggplot2 book.
In the exercise, the following code is provided:
fwd <- subset(mpg, drv == "f")
rwd <- subset(mpg, drv == "r")
ggplot(fwd, aes(displ, hwy, colour = class)) + geom_point()
ggplot(rwd, aes(displ, hwy, colour = class)) + geom_point()
Which produces the following output:
The following task is given: Modify the code so that the legend and axes match, without using facetting!
I am able to modify so that the axes match:
ggplot(fwd, aes(displ, hwy, colour = class)) + geom_point() + xlim(c(0, 7)) + ylim(c(0, 45))
ggplot(rwd, aes(displ, hwy, colour = class)) + geom_point() + xlim(c(0, 7)) + ylim(c(0, 45))
yielding:
But, I'm unable to get the legends to match. This question comes before scale_colour_manual() is explained, so I don't think we're supposed to use that.
Any ideas about how to get the legends to match?
Thanks!
Related
How can we set the breaks of continous axis every 2 numbers if we have a very big range of values in an axis and cannot set it manually?
p1 <- ggplot(mpg, aes(displ, hwy)) +
geom_point()
p1 + scale_x_continuous(breaks = c(2, 4, 6))
From the ?scale_x_continuous help page, breaks can be (among other options)
A function that takes the limits as input and returns breaks as output
The scales package offers breaks_width() for exactly this purpose:
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
scale_x_continuous(breaks = scales::breaks_width(2))
Here's an anonymous function going from the (floored) min to the (ceilinged) max by 2:
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
scale_x_continuous(breaks = \(x) seq(floor(x[1]), ceiling(x[2]), by = 2))
Alternately you could still use seq for finer control, more customizable, less generalizable:
ggplot(mpg, aes(displ, hwy)) +
geom_point() +
scale_x_continuous(breaks = seq(2, 6, by = 2))
I want to add a single point to only one facet. I tried to set the group in geom_point:
ggplot(data=mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(~class) + geom_point(aes(x=5, y=25, group = "pickup"), colour="blue")
But that put a blue dot in all facets. Is there any way to constrain the point to only one?
You could achieve your desired result by putting the information for your point in a dataframe which you pass to the data argument of your second geom_point:
library(ggplot2)
ggplot(data=mpg, aes(displ, hwy)) +
geom_point() +
facet_wrap(~class) +
geom_point(data = data.frame(displ = 5, hwy = 25, class = "pickup"), colour="blue")
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'm reading Hadley Wickham's ggplot2 book and would like to get comments on my solution to one of the exercises:
Section 6.5.1
Exercise 1
The following code creates two plots of the mpg dataset. Modify the code so that the legend and axes match, without using facetting!
fwd <- subset(mpg, drv == "f")
rwd <- subset(mpg, drv == "r")
ggplot(fwd, aes(displ, hwy, colour = class)) + geom_point()
ggplot(rwd, aes(displ, hwy, colour = class)) + geom_point()
Here's my solution:
ggplot(fwd, aes(displ, hwy, colour = class)) +
geom_point() +
lims(x = c(0, 7), y = c(0, 45)) +
geom_point(aes(colour = class), alpha = 0, data = mpg) +
guides(colour = guide_legend(override.aes = list(alpha = 1)))
ggplot(rwd, aes(displ, hwy, colour = class)) +
geom_point() +
lims(x = c(0, 7), y = c(0, 45)) +
geom_point(aes(colour = class), alpha = 0, data = mpg) +
guides(colour = guide_legend(override.aes = list(alpha = 1)))
I feel like my idea is smart, but it wouldn't be efficient for larger datasets. Is there a more direct way to solve this problem? Or is this what the exercise is aiming at?
Just use drop = FALSE to keep all the factor levels.
mpg$class <- as.factor(mpg$class) # convert to factor
fwd <- subset(mpg, drv == "f")
rwd <- subset(mpg, drv == "r")
ggplot(fwd, aes(displ, hwy, colour = class)) + geom_point() + scale_colour_discrete(drop=FALSE)
ggplot(rwd, aes(displ, hwy, colour = class)) + geom_point() + scale_colour_discrete(drop=FALSE)
I am new to ggplot. I am trying to understand how to use ggplot. I am reading Wickham's book and still trying to wrap my head around how to use aes() function.
What's the difference between these two implementations of aes():
library(ggplot2)
ggplot(mpg, aes(displ, hwy, colour = class)) +
geom_point() +
geom_smooth(method = "lm", se = FALSE) +
theme(legend.position = "none")
and
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(colour = class)) +
geom_smooth(method = "lm", se = FALSE) +
theme(legend.position = "none")
Both of them print significantly different graphs. Any help? I am really stuck.
In the first one you are mapping the aesthetics globally, ggplot will try to map these aesthetics to all other geom_xyz() layers.
While in the latter case, you are mapping aesethics to a specific ggplot layer (in your case geom_point())