I am trying to visualise data on a graph with R.
The code below works perfectly but the gridlines seem to be lost (see the image below).
with(res_final, plot(position_aa, mean_res, main="Hydrophobicity",
xlab="Amino acid position",
ylab="Eisenberg scale"))
with(res_final, points(position_aa, mean_res, pch=10, cex=0.5))
.col <- rgb(0, 0, 0, .25) ## alpha .25 for transparency
abline(h=axTicks(3), lty=3, col=.col)
abline(v=seq(-10:14), lty=3, col=.col)
I have positions from -10 to 14. How can I make the x axis with every single position separately labelled?
How can I add the gridlines to the plot below so that it is visible for each position from the x axis?
You haven't provided any data,but the following is a reasonable approximation:
set.seed(69)
res_final <- data.frame(position_aa = seq(-10, 14, 1),
mean_res = c(runif(10, -0.5, 0.25),
runif(4, 0.5, 1.25),
runif(11, -0.5, 0.25)))
The main problem with your code is your use of seq, which isn't doing what you think it is. The way to get a sequence between -10 and 14 is seq(-10, 14, 1) or seq(-10, 14). This change will allow your grid lines to appear as expected.
For your second problem, you can add an axis call using pos = 1 and the at argument to specify the breaks on the axis. You'll need to ensure that the plot area is wide enough (or the axis text is small enough) that some of the numbers don't get suppressed.
with(res_final, plot(position_aa, mean_res, main = "Hydrophobicity",
xlab = "Amino acid position",
ylab = "Eisenberg scale"))
axis(pos = 1, at = seq(-10, 14, 1))
with(res_final, points(position_aa, mean_res, pch = 10, cex = 0.5))
.col <- rgb(0, 0, 0, .25)
abline(h = axTicks(3), lty = 3, col = .col)
abline(v = seq(-10, 14, 1), lty = 3, col = .col)
For completeness, the equivalent in ggplot would be:
library(ggplot2)
ggplot(res_final, aes(position_aa, mean_res)) +
geom_point(shape = 21, size = 5, fill = "white") +
geom_point(shape = 21, size = 2, fill = "black") +
scale_x_continuous(breaks = seq(-10, 14)) +
theme_bw() +
theme(panel.grid.minor = element_blank(),
text = element_text(size = 15),
plot.title.position = "plot",
plot.title = element_text(hjust = 0.5)) +
labs(title = "Hydrophobicity",
x = "Amino acid position",
y = "Eisenberg scale")
Related
For the main y-axis and x-axis, I have generic titles like "Tank's Ratio" and "Counts". I want a second line of label where I specify the ratio and counts. eg. Just below "Tank's Ratio" I want "# in water/# in sand" in a smaller font but along the y-axis. Similarly for the x-axis.
Here is the basic code
data <- data.frame(set = c(1, 1, 1, 2, 2, 3, 3, 3, 3, 3, 4, 4), density = c(1, 3, 3, 1, 3, 1, 1, 1, 3, 3, 1, 3), counts = c(100, 2, 3, 76, 33, 12, 44, 13, 54, 36, 65, 1), ratio = c(1, 2, 3, 4, 1, 2, 3, 4, 5, 6, 90, 1))
library(ggplot2)
ggplot(data, aes(x = counts, y = ratio)) +
geom_point() +
ylab("Tank's Ratio") +
xlab("Counts")
You can add x and main titles.
EDIT: This is ridiculously slooow!
#library(extrafont)
#loadfonts(dev="win")
library(tidyverse)
data %>%
ggplot(aes(x=counts, y=ratio)) + geom_point() +
labs(y=expression(atop(bold("Tank's Ratio"),atop(italic("#in water #in sand")))))+
theme_minimal()+
theme(axis.title.y = element_text(size=15,family="Comic Sans MS"))
ORIGINAL:
library(tidyverse)
data %>%
ggplot(aes(x=counts, y=ratio)) + geom_point() +
labs(y="Tank's Ratio \n #in Water#in sand")
It's not the most elegant solution, but hope it helps:
library(ggplot2)
library(gridExtra)
library(grid)
First, create plot without ylab:
g <- ggplot(data, aes(x = counts, y = ratio)) +
geom_point() +
ylab("") +
xlab("Counts")
Then add subtitle for both axis:
g2 <- grid.arrange(g,
bottom = textGrob("in water/ # in sand",
x = 0.55, y = 1, gp = gpar(fontsize = 9)),
left = textGrob("in water/ # in sand", rot = 90,
x = 1.5, gp = gpar(fontsize = 9)))
And finally, add description of y-axis
grid.arrange(g2,
left = textGrob("Tank's Ratio", rot = 90,
x = 1.7, gp = gpar(fontsize = 12)))
You could use the following code, defining the margins, the axis titles and sub-titles yourself:
We use theme to increase the bottom and left margin, and to suppress the automatically generated axis titles.
We use annotate to generate the text that serves as axis title and sub-title, if necessary, the text is rotated.
We generate the plot, turn it in a grob, and with this grob we can turn of clipping, and show the plot.
g1 <- ggplot(data = data, aes(x = counts, y = ratio, group = 1)) +
geom_point() +
## increase margin size for left and bottom and
## remove the axis titles
theme(plot.margin = unit(c(1, 1, 4, 4), "lines"),
axis.title.y = element_blank(),
axis.title.x = element_blank() ) +
## define the plotting area to NOT include the annotations
coord_cartesian(xlim = c(0, 100), ylim= c(0, 100), expand = FALSE) +
## annotate y axis
annotate(geom = "text", x = -9, y = 50, label = "Tank's Ratio", angle = 90, size = 5) +
annotate(geom = "text", x = -5, y = 50, label = "#in water/#in sand", angle = 90, size = 4) +
## annotate x axis
annotate(geom = "text", x = 50, y = -5, label = "Counts", size = 5) +
annotate(geom = "text", x = 50, y = -9, label = "#in water/#in sand", size = 4)
## turn off clipping for axis extra labels
g2 <- ggplot_gtable(ggplot_build(g1))
g2$layout$clip[g2$layout$name == "panel"] <- "off"
grid::grid.draw(g2)
This yields the following picture:
Please let me know whether this is what you want.
Is there a way to add a line just to a continuous gradient legend? I was unable to find any examples of this using ggplot2.
For example, how could I add a red horizontal line to only the legend at say, 1.7?
library(ggplot2)
x <- seq(1:1000)
y <-rnorm(1000,0,1)
df <- data.frame(x,y)
ggplot(df, aes(x, y, color = y)) + geom_point()
Like this:
It might not make a lot of sense as to why I'd like that. For more context, I'm hoping to add a red line to the legend for these plots (at 4552), to show the capacity of a reservoir in the context of different annual reservoir inflow projections under different climate change scenarios, on a slide for discussion purposes (I don't need to annotate the red line). There are quite a few reservoirs, so if possible I'd like to do this all with R.
Thank you for any ideas.
Not sure how to add a custom line on gradient legend, but I do know how to add a custom tick label with custom color:
library(ggplot2)
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))
Notice that the "1.7" label overlaps the "2" label. You can either do something like the following:
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "<-- 1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))
or adjust the horizontal position of the "1.7" label:
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.hjust = c(0, 0, 0.1, 0),
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))
I am trying to add the below "graphic" to a chart I am doing in R.
I could easily do the graphic in a graphics application and then 'glue' it together with the R graph. However, it could be cool to make everything in R since it has the caveat that the position of the black arrow depends on calculated number. In the below case 6.8.
Any suggestions on how I could trick R to produce something like this?
This is a start for a function in base graphics:
draw <- function(x){
plot(NA, xlim=c(0,7), ylim=c(-.3,1), xaxt="n", yaxt="n", xlab="", ylab="")
lines(x=c(0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,0),
y=rep(c(0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0)))
lines(c(0,7),c(1,1))
for(i in 1:7) text(x = i-0.5, y= 0.5, labels=i)
arrows(0, 1.5, 7, 1.5, code=3)
polygon(x -1 +c(-.1, 0, .1),c(-.3,-0.05,-.3), col="black")
}
draw(4)
draw(3)
If you are interested in a base graphics function, you will probably want to make the width:heigth ratio fixed an change my polygon-triangle into a proper arrow, add some more text and things, but this should get you started:
Here's the ggplot2 solution:
df_nums <- data.frame(number <- 1:7,
fill <- c(rep("white", 5), "darkblue", "white"),
color <- c(rep("black", 5), "white", "black"))
df_text <- data.frame(label = c("Lower Risk", "Higher Risk", "Typically Lower Rewards",
"Typically Higher Rewards"),
hjust = c(0, 1, 0, 1),
x = c(0, 7, 0, 7),
y = c(2.9, 2.9, 2.1, 2.1))
arrow_x_pos <- 6.8 # position of arrow
p1 <- ggplot(df_nums) +
geom_tile(aes(x = number - .5, y = 1, fill = fill), size = 1, color = "black") +
geom_text(aes(x = number - .5, y = 1, color = color, label = number), size = 8) +
scale_color_identity(guide = "none") + scale_fill_identity(guide = "none") +
geom_text(data = df_text, aes(x = x, y = y, label = label, hjust = hjust), size = 5.5,
fontface = "bold") +
geom_text(aes(label = "Risk and Reward Profile", x = 0, y = 3.5),
fontface = "bold", size = 6.5, hjust = 0) +
geom_segment(x = 0, xend = 7, y = 2.5, yend = 2.5, size = 1,
arrow = arrow(length = unit(10,"pt"), ends = "both"),
color = "grey70") +
geom_segment(x = arrow_x_pos - 1, xend = arrow_x_pos - 1, y = -.3, yend = .2, size = 4,
arrow = arrow(length = unit(7, "pt"), type = "closed"),
lineend = "butt", linejoin = "mitre") +
ylim(-.2, 3.6) +
coord_fixed() +
theme_void()
p1
I'm trying to draw some arrows in the margin of a ggplot. From what I've read, you have to turn off the plot clipping to do that. However, when I do that, it deletes a line segment I have on my graph.
library(ggplot2)
library(ggrepel)
library(grid)
#----------------- Fake data practice --------------------- #
mydata <- data.frame(Labels = letters[1:14],
X_Values = seq(1, 14, 1),
Y_Values = rnorm(14, mean = 0, sd = 1),
Influence = seq(1, 14, 1))
mydata$Influencer <- factor(ifelse(mydata$Influence <= 3, 1, 0))
# --- Get min/max from data and use to set range at -1to1 or -2to2
chartMax <- ifelse(min(mydata$Y_Values) < -1 | max(mydata$Y_Values) > 1, 2, 1)
chartMin <- ifelse(chartMax == 1, -1, -2)
yTitle = "Some Title"
# --- Label setting, if greater than 0 nudge up, else nudge down
mydata$Nudger <- ifelse(mydata$Y_Values >= 0, .1, -.1)
p <- ggplot(mydata, aes(x = X_Values, y = Y_Values, group = Influencer)) +
geom_point(aes(size = Influencer, color = Influencer), shape = 18) +
geom_segment(x = 0, xend = 14, y = 0, yend = 0, color = "red", linetype = "dashed", size = 1.2, alpha = .5) +
geom_text_repel(aes(x = X_Values, y = Y_Values, label = Labels),
box.padding = .4,
point.padding = .2,
nudge_y = .1) +
scale_color_manual(values = c("grey", "blue")) +
scale_size_manual(values = c(4, 6)) +
scale_y_continuous(name = "", limits = c(chartMin, chartMax)) +
scale_x_continuous(name = yTitle,
limits = c(1, 15),
breaks = c(2,13),
labels = c("Lower", "Higher")) +
theme_classic() + theme(plot.margin = unit(c(1,3,1,2), "lines"),
legend.position="none",
axis.ticks.x=element_blank(),
axis.text.x = element_text(face = "bold"),
axis.title = element_text(face = "bold"),
axis.line.x = element_line(color = "blue"
,size = 1
,arrow =
arrow(length = unit(0.5, "cm"),
ends = "both"))) +
annotation_custom(
grob = linesGrob(arrow=arrow(type="open", ends="both", length=unit(0.5, "cm")), gp=gpar(col="blue", lwd=2)),
xmin = -1.4, xmax = -1.4, ymin = chartMin, ymax = chartMax
)
p
# Here it works and you see the red dashed line
# Turn off panel clipping
gt <- ggplot_gtable(ggplot_build(p))
gt$layout$clip[gt$layout$name == "panel"] <- "off"
grid.draw(gt)
Ideally, I want a blue arrow that runs alongside the y-axis in the margins. I think I've got that, but I can't loose my dashed red line that runs along the inside the graph.
I can't explain why this is happening (seems like a bug, I suggest raising an issue here), but I can confirm that the issue is related to the line alpha. If we delete the alpha = 0.5 argument from geom_segment then the clipping=off works without deleting the line:
Is there a way to add a line just to a continuous gradient legend? I was unable to find any examples of this using ggplot2.
For example, how could I add a red horizontal line to only the legend at say, 1.7?
library(ggplot2)
x <- seq(1:1000)
y <-rnorm(1000,0,1)
df <- data.frame(x,y)
ggplot(df, aes(x, y, color = y)) + geom_point()
Like this:
It might not make a lot of sense as to why I'd like that. For more context, I'm hoping to add a red line to the legend for these plots (at 4552), to show the capacity of a reservoir in the context of different annual reservoir inflow projections under different climate change scenarios, on a slide for discussion purposes (I don't need to annotate the red line). There are quite a few reservoirs, so if possible I'd like to do this all with R.
Thank you for any ideas.
Not sure how to add a custom line on gradient legend, but I do know how to add a custom tick label with custom color:
library(ggplot2)
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))
Notice that the "1.7" label overlaps the "2" label. You can either do something like the following:
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "<-- 1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))
or adjust the horizontal position of the "1.7" label:
ggplot(df, aes(x, y, color = y)) +
geom_point() +
scale_colour_gradient(breaks = c(-2, 0, 1.7, 2),
labels = c(-2, 0, "1.7 (important)", 2)) +
guides(color = guide_colorbar(barheight = 10,
label.hjust = c(0, 0, 0.1, 0),
label.theme = element_text(colour = c("black", "black",
"red", "black"),
angle = 0,
size = 12)))