set Y axis numbers in ggplot2 [duplicate] - r

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))

Related

Plot area reduces when x title includes superscript

I'm drawing a figure with two plots:
library(ggpubr)
library(ggplot2)
set.seed(123)
df <- data.frame(y= 1:20, x= sample(1:5, 20, replace= T))
A <- ggplot(df, aes(x, y)) + geom_point() + theme_bw() + labs(x= 'A (kg/mm^3)', y= 'B (%)')
B <- ggplot(df, aes(x, y)) + geom_point() + theme_bw() + labs(y= 'A (mm^2)', x= 'B (%)')
ggarrange(A, B)
When I include in one of the plots a superscript (in either the x or the y axis) the area of the plot reduces automatically a bit.
C <- ggplot(df, aes(x, y)) + geom_point() + theme_bw() + labs(x= expression(paste(paste("A (kg/", mm^3), ')')), y= expression('B (%)', c^2))
D <- ggplot(df, aes(x, y)) + geom_point() + theme_bw() + labs(y= expression(paste('A', mm^2)), x= expression('B (%)', c^2))
ggarrange(C, D)
I tried to reduce the area of the plot without a superscript by adding an expression that includes an invisible superscript (c^2) but the undesired area-reduction does not disappear.
For plot composition, package 'patchwork' is the best and easiest to use. It automatically aligns and resizes the plotting areas.
library(patchwork)
C | D

Add an extra point to a single facet in ggplot

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")

ggplot labels with "K" for thousands or "M" for millions (maintaining 'comma' y-axis labeling)

library(tidyverse)
df <- mpg %>% head() %>% mutate(hwy = hwy * 10000)
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = scales::comma) +
geom_text(aes(label = hwy), hjust = -0.25)
I want the labels on this plot to use "K" for thousands (eg 260K instead of 260000). BUT - I want to maintain the y-axis as is, with commas (eg 260,000). How can I achieve this?
You can use scales::label_number_si():
library(scales)
library(ggplot2)
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = comma) +
geom_text(aes(label = label_number_si()(hwy)), hjust = -0.25)
You can just add a custom column called myLabel to your dataframe which holds your desired labels. In the package scales you can find a function that does the converting part for you:
df <- mpg %>% head() %>% mutate(hwy = hwy * 10000)
df$myLabels <- scales::label_number_si()(df$hwy)
Now, use the new column myLabels as the aesthetic for creating the labels
ggplot(df, aes(cty, hwy)) +
geom_point() +
scale_y_continuous(label = scales::comma) +
geom_text(aes(label = myLabels), hjust = -0.25)

Matching legends for ggplot2

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!

In ggplot2, how to add text by group in facet_wrap?

Here is an example:
library(ggplot2)
set.seed(112)
df<-data.frame(g=sample(c("A", "B"), 100, T),
x=rnorm(100),
y=rnorm(100,2,3),
f=sample(c("i","ii"), 100, T))
ggplot(df, aes(x=x,y=y, colour=factor(g)))+
geom_point()+geom_smooth(method="lm", fill="NA")+facet_wrap(~f)
My question is how to add text like the second plot by group into the plot.
You can manually create another data.frame for your text and add the layer on the original plot.
df_text <- data.frame(g=rep(c("A", "B")), x=-2, y=c(9, 8, 9, 8),
f=rep(c("i", "ii"), each=2),
text=c("R=0.2", "R=-0.3", "R=-0.05", "R=0.2"))
ggplot(df, aes(x=x,y=y, colour=factor(g))) +
geom_point() + geom_smooth(method="lm", fill="NA") +
geom_text(data=df_text, aes(x=x, y=y, color=factor(g), label=text),
fontface="bold", hjust=0, size=5, show.legend=FALSE) +
facet_wrap(~f)
Another option is to calculate the correlations on the fly and use the underlying numeric values of the factor variable g to place the text so that the red and blue labels don't overlap. This reduces the amount of code needed and makes label placement a bit easier.
library(dplyr)
ggplot(df, aes(x=x, y=y, colour=g)) +
geom_point() +
geom_smooth(method="lm", fill=NA) + # Guessing you meant fill=NA here
#geom_smooth(method="lm", se=FALSE) # Better way to remove confidence bands
facet_wrap(~f) +
geom_text(data=df %>% group_by(g, f) %>% summarise(corr = cor(x,y)),
aes(label=paste0("R = ", round(corr,2)), y = 10 - as.numeric(g)),
x=-2, hjust=0, fontface="bold", size=5, show.legend=FALSE)

Resources