Setting only certain tick marks in Ggplot2 - r

I want to recreate the following plot which only shows tick marks on y and x axis at the start and the end of the line.
Picture of Plot.
I have the following code so far:
elevation_plot <- StradeBianche%>%
ggplot(aes(x = `Accumulated Distance in Km`))+
geom_area(aes(y = elevation), fill = "grey")+
coord_cartesian(ylim = c(100,500))+
scale_y_continuous(expand = c(0,0), limits = c(0, 500), labels = label_number(suffix = " m"))+
scale_x_continuous(expand = c(0,0), breaks = seq(0, 180, 20), labels = label_number(suffix = ".0 km"))+
theme(panel.grid.minor = element_blank())+
theme(panel.grid.major = element_blank())+
theme(panel.background = element_rect(fill = "white"))+
theme(panel.border = element_blank())+
theme(axis.title = element_blank())+
theme(axis.ticks = element_blank())
The result is this:Picture of result. It comes quite close but the ticks are still missing...
I can either remove all axis ticks or none. But I can not manage to set only certain axis ticks without removing the x and y values along the axis.
Any help is greatly appreciated!

You could use the pretty_breaks function from the scales library:
ggplot(dat, aes(x,y)) + geom_point() +
scale_x_continuous(breaks = scales::pretty_breaks(n = 10)) +
scale_y_continuous(breaks = scales::pretty_breaks(n = 10))
Where n defines the number of ticks
Check out https://stackoverflow.com/a/31408489/15235792

You can immitate ticks behaviour if you place geom_segment()s at the right coordinates and turn off the clipping of the data. The downside is that you cannot place the segment endpoints relative to the first in absolute units, so you'd have to fiddle with the offset and text margins. Example below:
library(ggplot2)
xlim <- c(1, 5)
ylim <- c(4, 8)
offset <- 0.05
seg <- data.frame(
x = xlim[c(1,2,1,1)],
xend = xlim[c(1,2,1,1)] - c(0, 0, offset, offset),
y = ylim[c(1,1,2,1)],
yend = ylim[c(1,1,2,1)] - c(offset, offset, 0, 0)
)
ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
geom_point(aes(colour = Species)) +
geom_segment(data = seg, aes(x = x, y = y, xend = xend, yend = yend)) +
coord_cartesian(clip = "off",
xlim = xlim,
ylim = ylim,
expand = FALSE) +
theme(axis.ticks = element_blank(),
axis.line = element_line(),
axis.text.x = element_text(margin = margin(t = 8)),
axis.text.y = element_text(margin = margin(r = 8)))
Created on 2021-03-25 by the reprex package (v1.0.0)

Related

how to limit a logarithmic axis

I am trying to plot a curve with the following command but I need to limit the y-axis until 100, so can anybody help me find out how to do it?
Thanks in advance
ggplot(file1, aes(x=f11,colour=time, alpha=time, size=time))+
geom_line(aes(y = S1))+scale_color_manual(values =c("t1"="red","t2"="magenta","t3"="coral4","t5"=cl[8]),
labels=labels1 ,name="Time")+
scale_alpha_manual(values=c(1, 1, 1, 1),labels=labels1)+
scale_size_manual(values = c(.6, .61, .61, .61),labels=labels1)+
guides(colour = guide_legend(title=title),
alpha = guide_legend(title=title),
size = guide_legend(title=title))+
labs(title="Column 1")+ theme_bw()+theme(plot.title=element_text(size=12,hjust=0.5,face="bold"))+
theme(aspect.ratio = 1)+ theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank())+
xlab( growth)+ylab(nutrient )+
scale_x_continuous(breaks = seq(0, 0.5, by=0.10), limits=c(0,0.5))+
scale_y_continuous(trans='log10')
You can use the function scale_y_log10 and set limits like in the following code:
library(ggplot2)
ggplot(data = df,aes(x = x, y =y)) +
geom_point() +
scale_y_log10(limits = c(1,100))
Output:
Data
df <- data.frame(x = 1:10, y = seq(1,150,length.out = 10))

R ggplot set origin when using a log scale

The last line in the following code sets the origin of the plot at zero for the y-scale and the y-scale's limits. How do I do this for the x-scale when using a log10 grid?
breaks <- 10^(-10:10) # break for major axis
minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each = 9)) # breaks for minor axis
ggplot(data = cars, aes(x = dist, y = speed)) +
geom_point() +
scale_x_log10(breaks = breaks, minor_breaks = minor_breaks) + # use log10 scale for x
theme(panel.grid.major = element_line(colour = "grey50")) +
theme(panel.grid.minor = element_line(colour = "grey70")) +
theme_light(base_size = 12) +
scale_y_continuous(expand = c(0, 0), limits = c(0,30)) # sets origin and limits for y-scale
I suggest using a modified transformation, pseudo_log_trans, which accommodates zero values (and even negatives) by smoothly transitioning between a linear scale in [-1, 1] and a signed log scale beyond that range. The approximate point of transition can be modified using the first parameter, sigma.
ggplot(data = cars, aes(x = dist, y = speed)) +
geom_point() +
scale_x_continuous(trans = scales::pseudo_log_trans(1)) +
theme(panel.grid.major = element_line(colour = "grey50")) +
theme(panel.grid.minor = element_line(colour = "grey70")) +
theme_light(base_size = 12) +
coord_cartesian(expand = FALSE, # EDIT #2
xlim = c(0, 130), ylim = c(0, 30))
Here's how it transitions between the linear and log scales:
plot(scales::pseudo_log_trans(), xlim = c(-5, 10))
lines(scales::log_trans(), xlim = c(-5, 10), col = "red")

Limit the X and Y axes of ggplot2 plot

I'm using secondary axes (scaled) to show metric/imperial units for a plot. I'd like to have the plot area to be limited to (1500,0) and (5000,350) - both sets in principal coordinates. I've tried the following:
xlim(c(1500,5000)) + ylim(c(0,350))
lims with the same arguments as above
coord_cartesian(xlim = c(1500, 5000), ylim = c(0, 350))
None of these made any change to my plot. I'd like to get rid of the areas highlighted by the red lines (crop the plot):
Here's a minimal working example using mtcars - despite specifying the upper x-limit to be 10, the plot shows data past that range. I'd like the plot to cropped to the limits specified. Is there a way to do this?
ggplot(as.data.table(mtcars)) +
geom_line(aes(x = wt, y = mpg, color= factor(cyl))) +
ylab('Fuel Economy (mpg)') +
scale_y_continuous(sec.axis = sec_axis(~.*1.6/3.7854, name = 'Fuel Economy (kmpl)')) +
xlab('Weight (lbs)') +
scale_x_continuous(sec.axis = sec_axis(~./2.20462, name = 'Weight (kg)'), position = 'bottom') +
theme_light() +
theme(
legend.position = c(0.15, 0.75),
legend.title = element_blank(),
axis.title.y.right = element_text(
angle = 90,
margin = margin(r = 0.8 * 11,
l = 0.8 * 11 / 2)
)
) +
coord_cartesian(xlim = c(0, 5), ylim = c(10, 35))
Add limits and expand arguments in scale_x_continuous and scale_y_continuous. You can add breaks as well.
ggplot(as.data.table(mtcars)) +
geom_line(aes(x = wt, y = mpg, color= factor(cyl))) +
ylab('Fuel Economy (mpg)') +
scale_y_continuous(limits = c(10, 35), expand = c(0, 0),
sec.axis = sec_axis(~.*1.6/3.7854, name = 'Fuel Economy (kmpl)')
) +
xlab('Weight (lbs)') +
scale_x_continuous(limits = c(0, 5), expand = c(0, 0),
sec.axis = sec_axis(~./2.20462, name = 'Weight (kg)'), position = 'bottom') +
theme_light() +
theme(
legend.position = c(0.15, 0.75),
legend.title = element_blank(),
axis.title.y.right = element_text(
angle = 90,
margin = margin(r = 0.8 * 11,
l = 0.8 * 11 / 2)
)
)

R ggridges plot - Showing y axis ticks and labels

I am trying to generate overlay density plots over time, comparing densities of males vs. females. Here is my output:
I am following the Australian athletes height example from https://cran.r-project.org/web/packages/ggridges/vignettes/gallery.html.
Here is my code:
ggplot(math_dat, aes(x = order_math, y = time, color = gender, point_color = gender, fill = gender)) +
geom_density_ridges(
jittered_points = TRUE, scale = .95, rel_min_height = .01,
point_shape = "|", point_size = 3, size = 0.25,
position = position_points_jitter(height = 0)
) +
scale_y_discrete(expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0), name = "Rankings") +
scale_fill_manual(values = c("#D55E0050", "#0072B250"), labels = c("female", "male")) +
scale_color_manual(values = c("#D55E00", "#0072B2"), guide = "none") +
scale_discrete_manual("point_color", values = c("#D55E00", "#0072B2"), guide = "none") +
coord_cartesian(clip = "off") +
guides(fill = guide_legend(
override.aes = list(
fill = c("#D55E00A0", "#0072B2A0"),
color = NA, point_color = NA)
)
) +
ggtitle("Ranks over time") +
theme_ridges(center = TRUE)
My problem is I am unable to generate any Y axis tick values and the example doesn't display any either. Any ideas how to get Y axis tick marks to display?
Here is some sample data similar to mine:
## generating dataset
order_math<-c(1,2,1,2,3,3,1,2,3,1,2,3)
gender<-c("M","F","M","M","M","F","F","M","F","M","M","F")
time<-c(1,1,2,3,3,2,1,2,3,2,3,1)
sample<-data.frame(order_math,gender,time)
UPdate:
After #Tomasu's suggestions I have updated my code, but it does not run:
ggplot(math_dat, aes(x = order_math, y = time, color = gender, point_color = gender, fill = gender)) +
geom_density_ridges(
jittered_points = TRUE, scale = .95, rel_min_height = .01,
point_shape = "|", point_size = 3, size = 0.25,
position = position_points_jitter(height = 0)
) +
scale_y_reverse(limits = c(1000, 500, 100),expand = c(0, 0)) +
scale_x_continuous(expand = c(0, 0), name = "Rankings") +
scale_fill_manual(values = c("#D55E0050", "#0072B250"), labels = c("female", "male")) +
scale_color_manual(values = c("#D55E00", "#0072B2"), guide = "none") +
scale_discrete_manual("point_color", values = c("#D55E00", "#0072B2"), guide = "none") +
coord_cartesian(clip = "off") +
guides(fill = guide_legend(
override.aes = list(
fill = c("#D55E00A0", "#0072B2A0"),
color = NA, point_color = NA)
)
) +
ggtitle("Ranks over time") +
theme_ridges(center = TRUE)+
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
)
An easy solution to this problem would be to use a theme_ that includes the axis ticks as theme_ridges() has them turned off. Just removing that theme all together and using the base ggplot2 theme achieves the desired outcome.
However, let's say we still want to use theme_ridges() and just turn ticks back on. This can be achieved with a theme() edit after the theme_ridges().
I'm using the example in the link provided as I couldn't get your sample data to work properly.
library(ggplot2)
library(ggplot2movies)
library(ggridges)
ggplot(movies[movies$year>1912,], aes(x = length, y = year, group = year)) +
geom_density_ridges(scale = 10, size = 0.25, rel_min_height = 0.03) +
theme_ridges() +
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
) +
scale_x_continuous(limits = c(1, 200), expand = c(0, 0)) +
scale_y_reverse(
breaks = c(2000, 1980, 1960, 1940, 1920, 1900),
expand = c(0, 0)
) +
coord_cartesian(clip = "off")
Created on 2021-05-11 by the reprex package (v1.0.0)
I think your problem is that you need to specify the group.
Related thread: geom_density_ridges requires the following missing aesthetics: y
Extending on code from user tomasu's answer +1
library(ggridges)
library(ggplot2)
order_math<-c(1,2,1,2,3,3,1,2,3,1,2,3)
gender<-c("M","F","M","M","M","F","F","M","F","M","M","F")
time<-c(1,1,2,3,3,2,1,2,3,2,3,1)
sample<-data.frame(order_math,gender,time)
ggplot(sample, aes(x = order_math, y = time, group = time,
color = gender, point_color = gender, fill = gender)) +
geom_density_ridges() +
theme(
axis.ticks = element_line(size=0.5), # turn ticks back on
axis.ticks.length = grid::unit(5, "pt"), # set length
axis.ticks.y = element_line(colour = "red"), # define tick line color
axis.text.y = element_text(vjust = .4) # center text with tick
)
#> Picking joint bandwidth of 0.555
Created on 2021-05-12 by the reprex package (v2.0.0)

Log scale on y axis but data have negative values

I am trying to create a boxplot with a log y axis as I have some very small values and then some much higher values which do not work well in a boxplot with a continuous y axis. However, I have negative values which obviously do not work with a log scale. I was wondering if there was a way around this so that I can display my data on a boxplot which is still easy to interpret but has a more appropriate scale on the y axis.
p <- ggplot(data = Elstow.monthly.fluxes, aes(x = Month1, y = CH4.Flux)) + stat_boxplot(geom = "errorbar", linetype = 1, width = 0.5) + geom_boxplot() +
xlab(expression("Month")) + ylab(expression(~CH[4]~Flux~(µg~CH[4]~m^{-2}~d^{-1}))) +
scale_y_continuous(breaks = seq(-5000,40000,5000), limits = c(-5000,40000))+
theme(axis.text.x = element_text(colour = "black")) + theme(axis.text.y = element_text(colour =
"black")) +
theme(panel.background = element_rect("white", "black")) +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
theme(axis.text = element_text(size = 12))+ theme(axis.title = element_text(size = 14))+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 15, b = 0, l = 0))) +
theme(axis.title.x = element_text(margin = margin(t = 15, r = 0, b = 0, l = 0))) +
geom_hline(yintercept = 0, linetype ="dashed", colour = "black")
While you could indeed use the secondary axis to get the labels you want as Zhiqiang suggests, you could also use a transformation that fits your needs.
Consider the following skewed boxplots:
df <- data.frame(
x = rep(letters[1:2], each = 500),
y = rlnorm(1000) - 2
)
ggplot(df, aes(x, y)) +
geom_boxplot()
Instead, you could use the pseudo-log transformation to visualise your data:
ggplot(df, aes(x, y)) +
geom_boxplot() +
scale_y_continuous(trans = scales::pseudo_log_trans())
Alternatively, you could make any transformation you want. I personally like the inverse hyperbolic sine transformation, which is very much like the pseudo-log:
asinh_trans <- scales::trans_new(
"inverse_hyperbolic_sine",
transform = function(x) {asinh(x)},
inverse = function(x) {sinh(x)}
)
ggplot(df, aes(x, y)) +
geom_boxplot() +
scale_y_continuous(trans = asinh_trans)
I have a silly solution: trick the secondary axis to re-scale y axis. I do not have your data, just made up some numbers for the purpose of demonstration.
First convert y values as logy = log(y + 5000). When generating the graph, transform the values back to the original scale. I borrow the second axis to display the values. I am pretty sure others may have more elegant ways to do this.
I was lazy for not trying to find the right way to remove the primary y axis tick labels, just used breaks = c(0).
df<-data.frame(y = runif(33, min=-5000, max=40000),
x = rep(c("Aug", "Sep", "Oct"),33))
library(tidyverse)
df$logy = log(df$y+5000)
p <- ggplot(data = df, aes(x = x, y = logy)) +
stat_boxplot(geom = "errorbar", linetype = 1, width = 0.5) +
geom_boxplot() +
xlab(expression("Month")) +
ylab(expression(~CH[4]~Flux~(µg~CH[4]~m^{-2}~d^{-1}))) +
scale_y_continuous(sec.axis = sec_axis(~(exp(.) -5000),
breaks = c(-4000, 0, 5000, 10000, 20000, 40000)),
breaks = c(0))+
theme(axis.text.x = element_text(colour = "black")) +
theme(axis.text.y = element_text(colour = "black")) +
theme(panel.background = element_rect("white", "black")) +
theme(panel.border = element_rect(colour = "black", fill=NA, size=0.5)) +
theme(axis.text = element_text(size = 12))+
theme(axis.title = element_text(size = 14))+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 15, b = 0, l = 0))) +
theme(axis.title.x = element_text(margin = margin(t = 15, r = 0, b = 0, l = 0))) +
geom_hline(yintercept = log(5000), linetype ="dashed", colour = "black")
p
coord_trans() is applied after the statistics are calculated (unlike scale). This can be combined with the pseudo_log_trans to cope with negatives.
library(plotly)
set.seed(1234)
dat <- data.frame(cond = factor(rep(c("A","B"), each=200)), rating = c(rnorm(200),rnorm(200, mean=500)))
pseudoLog <- scales::pseudo_log_trans(base = 10)
p <- ggplot(dat, aes(x=cond, y=rating)) + geom_boxplot() + coord_trans(y=pseudoLog)

Resources