Fix log plot in R - r

I want a plot with a log scale in x-axis and a "normal" y-axis.
I got a plot but I see a strange thing on my y-axis which I couldnt figure out.
breaks <- 10^(-10:10)
minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))
ggplot(mtcars, aes(mpg, disp)) +
geom_line(size = 1, color = "blue") +
scale_x_log10(breaks = breaks, minor_breaks = minor_breaks, limits = c(0.1,50)) +
annotation_logticks()
What is this thing on the y-axis and how can I get rid of it?

Using the code below you can remove the black mess on the y-axis because it's the annotated tick marks you've added. Setting side = "b" indicates that you only want the tick marks on the x-axis (the bottom).
breaks <- 10^(-10:10)
minor_breaks <- rep(1:9, 21)*(10^rep(-10:10, each=9))
g <- ggplot(mtcars, aes(mpg, disp)) +
geom_line(size = 1, color = "blue") +
scale_x_log10(breaks = breaks, minor_breaks = minor_breaks, limits = c(0.1,50)) +
annotation_logticks(sides = "b")
g

By default annotation_logticks() adds ticks to the bottom and left axis. You don't want ticks on the left (y-axis) because it isn't log-scaled. That's why it looks wrong.
Use the sides = argument to label only the bottom (x-axis):
g <- ggplot(mtcars, aes(mpg, disp)) +
geom_line(size = 1, color = "blue") +
scale_x_log10(breaks = breaks, minor_breaks = minor_breaks, limits = c(0.1, 50)) +
annotation_logticks(sides = "b")

Related

Add label between colorbar breaks in ggplot2

I am trying to create a figure with ggplot and would like to add category names between colorbar breaks (values). I am using a graduated colorbar using the scale_color_fermenter function, which I think makes it a bit tricky to do this.
Below is an example code
library('ggplot2')
ggplot(mtcars, aes(x=mpg, y=carb, color=disp)) +
geom_point(size=3)+
scale_color_fermenter(breaks = c(100,300,400), palette = "Blues") #graduate colorbar
The resulting figure looks like this
I want to add categories (A, B, C, etc.) between the colorbar breaks (i.e., create categories for disp), such that
0<=A<100
100<=B<300
300<=C<400
400<=D<500
The resulting figure looks like this (or similar)
I know I can add extra breaks and change the label. Something like the following
scale_color_fermenter(breaks=c(50,100,200,300,350,400,450,500),
labels=c('A','100','B','300','C','400','D','500'))
But this would mess up the colorbar class (i.e., colorbar will have more colors), which is something I do not want.
Basically the same approach as by #zephryl but with some additional styling and fiddling and using ggtext::element_markdown just in case you want some additional styling for the text labels.
Using lineheight I add some padding between the tick and the category labels.
Using vjust I shift the labels so that the position of the tick labels corresponds approximately to the boundaries of the legend keys.
library("ggplot2")
mylabels <- function(x) {
paste0(
c(rep("", length(x) - 1), paste0("<span style='color: red'>", LETTERS[length(x) + 1], "</span><br>")),
x,
"<br><span style='color: red'>", LETTERS[seq_along(x)], "</span>"
)
}
ggplot(mtcars, aes(x = mpg, y = carb, color = disp)) +
geom_point(size = 3) +
scale_color_fermenter(breaks = c(100, 300, 400), labels = mylabels, palette = "Blues") +
theme(legend.text = ggtext::element_markdown(vjust = c(.85, .85, .55), lineheight = 1.25))
How about:
library(ggplot2)
ggplot(mtcars, aes(x = mpg, y = carb, color = disp)) +
geom_point(size = 3)+
scale_color_fermenter(
breaks = c(100,300,400),
labels = c("B\n100\nA", "C\n300\n", "D\n400\n"),
palette = "Blues"
)
Created on 2022-10-27 with reprex v2.0.2
An alternative is to draw the letters on as annotations:
ggplot(mtcars, aes(mpg, carb, color = disp)) +
geom_point(size = 3) +
scale_color_fermenter(breaks = c(100, 300, 400)) +
coord_cartesian(clip = "off") +
annotation_custom(grid::textGrob(c("A", "B", "C", "D"),
x = 1.02, y = seq(0.39, 0.57, 0.058))) +
theme(legend.box.margin = margin(10, 10, 10, 10))

Inner ticks in ggplot

I want to add inner ticks to my plot given by a vector.
say my vector is myvec <- c(1,3,4:9, 12, 15)
and my plot:
library(ggplot2)
df <- data.frame(x=seq(1:100), y=sort(rexp(100, 2), decreasing = T))
ggplot(df, aes(x=x, y=y)) + geom_point() +
scale_y_continuous(limits = c(0, 4))
I now want to add inside facing ticks at x= myvec, y=0 in blue color. How do I do it?
Tried to work with this solution, but could not use the vector.
Annotate ggplot with an extra tick and label
Try This:
df2<- cbind.data.frame("myvec" = myvec, z= rep(0, length(myvec)))
ggplot(df, aes(x=x, y=y)) + geom_point() +
scale_y_continuous(limits = c(0, 4)) +
geom_point(data=df2, aes(x=myvec, y=z), shape = "\U2714", color = "blue", size= 2)

How to colour background on a scatterplot using ggplot but still show data points in R?

This is my first question here so hope this makes sense and thank you for your time in advance!
I am trying to generate a scatterplot with the data points being the log2 expression values of genes from 2 treatments from an RNA-Seq data set. With this code I have generated the plot below:
ggplot(control, aes(x=log2_iFGFR1_uninduced, y=log2_iFGFR4_uninduced)) +
geom_point(shape = 21, color = "black", fill = "gray70") +
ggtitle("Uninduced iFGFR1 vs Uninduced iFGFR4 ") +
xlab("Uninduced iFGFR1") +
ylab("Uninduced iFGFR4") +
scale_y_continuous(breaks = seq(-15,15,by = 1)) +
scale_x_continuous(breaks = seq(-15,15,by = 1)) +
geom_abline(intercept = 1, slope = 1, color="blue", size = 1) +
geom_abline(intercept = 0, slope = 1, colour = "black", size = 1) +
geom_abline(intercept = -1, slope = 1, colour = "red", size = 1) +
theme_classic() +
theme(plot.title = element_text(hjust=0.5))
Current scatterplot:
However, I would like to change the background of the plot below the red line to a lighter red and above the blue line to a lighter blue, but still being able to see the data points in these regions. I have tried so far by using polygons in the code below.
pol1 <- data.frame(x = c(-14, 15, 15), y = c(-15, -15, 14))
pol2 <- data.frame(x = c(-15, -15, 14), y = c(-14, 15, 15))
ggplot(control, aes(x=log2_iFGFR1_uninduced, y=log2_iFGFR4_uninduced)) +
geom_point(shape = 21, color = "black", fill = "gray70") +
ggtitle("Uninduced iFGFR1 vs Uninduced iFGFR4 ") +
xlab("Uninduced iFGFR1") +
ylab("Uninduced iFGFR4") +
scale_y_continuous(breaks = seq(-15,15,by = 1)) +
scale_x_continuous(breaks = seq(-15,15,by = 1)) +
geom_polygon(data = pol1, aes(x = x, y = y), color ="pink1") +
geom_polygon(data = pol2, aes(x = x, y = y), color ="powderblue") +
geom_abline(intercept = 1, slope = 1, color="blue", size = 1) +
geom_abline(intercept = 0, slope = 1, colour = "black", size = 1) +
geom_abline(intercept = -1, slope = 1, colour = "red", size = 1) +
theme_classic() +
theme(plot.title = element_text(hjust=0.5))
New scatterplot:
However, these polygons hide my data points in this area and I don't know how to keep the polygon color but see the data points as well. I have also tried adding "fill = NA" to the geom_polygon code but this makes the area white and only keeps a colored border. Also, these polygons shift my axis limits so how do I change the axes to begin at -15 and end at 15 rather than having that extra unwanted length?
Any help would be massively appreciated as I have struggled with this for a while now and asked friends and colleagues who were unable to help.
Thanks,
Liv
Your question has two parts, so I'll answer each in turn using a dummy dataset:
df <- data.frame(x=rnorm(20,5,1), y=rnorm(20,5,1))
Stop geom_polygon from hiding geom_point
Stefan had commented with the answer to this one. Here's an illustration. Order of operations matters in ggplot. The plot you create is a result of each geom (drawing operation) performed in sequence. In your case, you have geom_polygon after geom_point, so it means that it will plot on top of geom_point. To have the points plotted on top of the polygons, just have geom_point happen after geom_polygon. Here's an illustrative example:
p <- ggplot(df, aes(x,y)) + theme_bw()
p + geom_point() + xlim(0,10) + ylim(0,10)
Now if we add a geom_rect after, it hides the points:
p + geom_point() +
geom_rect(ymin=0, ymax=5, xmin=0, xmax=5, fill='lightblue') +
xlim(0,10) + ylim(0,10)
The way to prevent that is to just reverse the order of geom_point and geom_rect. It works this way for all geoms.
p + geom_rect(ymin=0, ymax=5, xmin=0, xmax=5, fill='lightblue') +
geom_point() +
xlim(0,10) + ylim(0,10)
Removing whitespace between the axis and limits of the axis
The second part of your question asks about how to remove the white space between the edges of your geom_polygon and the axes. Notice how I have been using xlim and ylim to set limits? It is a shortcut for scale_x_continuous(limits=...) and scale_y_continuous(limits=...); however, we can use the argument expand= within scale_... functions to set how far to "expand" the plot before reaching the axis. You can set the expand setting for upper and lower axis limits independently, which is why this argument expects a two-component number vector, similar to the limits= argument.
Here's how to remove that whitespace:
p + geom_rect(ymin=0, ymax=5, xmin=0, xmax=5, fill='lightblue') +
geom_point() +
scale_x_continuous(limits=c(0,10), expand=c(0,0)) +
scale_y_continuous(limits=c(0,10), expand=c(0,0))

scale on bar plot in reverse direction - ggplot2

The code below is from Creating a horizontal bar plots in the reverse direction.
I'd like to make a horizontal bar chart in the reverse direction but with a fixed scale. I'd like the scale of the plot to be fixed to 0 to 50 rather than the current 0 to 30.
I've tried changing scale_y_continuous() to scale_y_discret() and I've tried adding ylim() but I can't seem to get it to work.
Thanks!
mtcars
mtcars$`car name` <- rownames(mtcars)
ggplot (mtcars, aes (x=`car name`, y=-mpg)) +
geom_bar (position = position_dodge(), stat = "identity",fill="red",colour="black") +
coord_flip () + theme_classic() +
scale_x_discrete(name = "", position = "top") +
scale_y_continuous(name = "mpg",
breaks = seq(0, -30, by = -10),
labels = seq(0, 30, by = 10)) + theme(axis.text.y = element_blank())
you can use limits to set a limit on your y scale, It's a numeric vector of length two describing the scale limits.
as #jimbou mentioned in the comments, your code will be something like this:
ggplot (mtcars, aes (x=`car name`, y=-mpg)) +
geom_bar (position = position_dodge(), stat = "identity",fill="red",colour="black") +
coord_flip () + theme_classic() +
scale_x_discrete(name = "", position = "top") +
scale_y_continuous(name = "mpg",
limits = c(-50,0),
breaks = seq(0, -50, by = -10),
labels = seq(0, 50, by = 10)) + theme(axis.text.y = element_blank())
you can also see here

Expand y scale but limit height of y axis line

My goal is to make a simple column chart in ggplot2 that looks like the following chart (made in Excel):
What I'm finding is that, with example data such as this (where one percentage value is very close to 100%), my options for plotting this data in ggplot2 leave something to be desired. In particular, I haven't found a way to make the following two simple things happen together:
1) Make the y-axis line end at 100%
and
2) Make the percentage labels over each bar visible
To address this issue, I've tried experimenting with different arguments to scale_y_continuous() but haven't found a way to meet both of the goals above at the same time. You can see this in the example plots and code below.
My question is: how do I expand the y scale so that my percentage labels over each data point are visible, but the y-axis line ends at 100%?
library(dplyr)
library(ggplot2)
library(scales)
example_df <- data_frame(Label = c("A", "B"),
Percent = c(0.5, 0.99))
example_plot <- example_df %>%
ggplot(aes(x = Label, y = Percent)) +
geom_bar(stat = "identity",
fill = "dodgerblue4", width = .6) +
geom_text(aes(label = percent(Percent)),
size = 3, vjust = -0.5) +
scale_x_discrete(NULL, expand = c(0, .5)) +
theme_classic()
Plot with desired y-axis line, but non-visible label over bar
Here is what happens when I set the limit on scale_y_continuous() to c(0,1):
example_plot +
scale_y_continuous(NULL, limits = c(0, 1.0), breaks = seq(0, 1, .2),
labels = function(x) scales::percent(x),
expand = c(0, 0)) +
labs(title = "Y axis line looks perfect, but the label over the bar is off")
Plot with y-axis line too long, but visible label over bar
And here is what happens when I set the limit on scale_y_continuous() to c(0,1.05):
example_plot +
scale_y_continuous(NULL, limits = c(0, 1.05), breaks = seq(0, 1, .2),
labels = function(x) scales::percent(x),
expand = c(0, 0)) +
labs(title = "Y axis line is too long, but the label over the bar is visible")
You could remove the regular axis line and then use geom_segment to create a new one:
example_df %>%
ggplot(aes(x = Label, y = Percent)) +
geom_bar(stat = "identity", fill = "dodgerblue4", width = .6) +
geom_text(aes(label = percent(Percent)), size = 3, vjust = -0.5) +
scale_x_discrete("", expand = c(0, .5)) +
scale_y_continuous("", breaks = seq(0, 1, .2), labels = percent, limits=c(0,1.05),
expand=c(0,0)) +
theme_classic() +
theme(axis.line.y=element_blank()) +
geom_segment(x=.5025, xend=0.5025, y=0, yend=1.002)
To respond to your comment: Even when it's outside the plot area, the 99% label is still being drawn, but it's "clipped", meaning that plot elements outside the plot area are masked. So, another option, still hacky, but less hacky than my original answer, is to turn off clipping so that the label appears:
library(grid)
p = example_df %>%
ggplot(aes(x = Label, y = Percent)) +
geom_bar(stat = "identity", fill = "dodgerblue4", width = .6) +
geom_text(aes(label = percent(Percent)), size = 3, vjust = -0.5) +
scale_x_discrete("", expand = c(0, .5)) +
scale_y_continuous("", breaks = seq(0, 1, .2), labels = percent, limits=c(0,1),
expand=c(0,0)) +
theme_classic() +
theme(plot.margin=unit(c(10,0,0,0),'pt'))
# Turn off clipping
pg <- ggplot_gtable(ggplot_build(p))
pg$layout$clip[pg$layout$name=="panel"] <- "off"
grid.draw(pg)

Resources