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))
Related
I am trying to add labels in line graph but am unable to do so.
I want to add lable such that blue line mentiones 'model_1'; red line mentioned 'model_2' and darkgreen line mentioned 'model_3'
Attaching the code below
p1 <- ggplot(data = Auto, aes(x = horsepower, y = mpg)) +
geom_point() +
geom_line(aes(y = fitted(lm_mpg_1)), color = "blue", size = 1) +
geom_line(aes(y = fitted(lm_mpg_2)), color = "red", size = 1) +
geom_line(aes(y = fitted(lm_mpg_3)), color = "darkgreen", size = 1)
I have tried to use geom_text, geom_label and annotate function however they give me error.
The code I tried was:
p1 + geom_text(label = c('model_1','model_2','model_3'))
You don't have any data. You can use dput to share your data. In the meanwhile I have used mtcars as an example below:
# library
library(ggplot2)
# Keep 30 first rows in the mtcars natively available dataset
data=head(mtcars, 30)
# 1/ add text with geom_text, use nudge to nudge the text
ggplot(data, aes(x=wt, y=mpg)) +
geom_point() + # Show dots
geom_text(
label=rownames(data),
nudge_x = 0.25, nudge_y = 0.25,
check_overlap = T
)
ggplot(data, aes(x=wt, y=mpg)) +
geom_point() + # Show dots
geom_label(
label=rownames(data),
nudge_x = 0.25, nudge_y = 0.25,
check_overlap = T
)
p <- ggplot(mtcars, aes(x = wt, y = mpg)) + geom_point()
p + annotate("text", x = 4, y = 25, label = "Some text")
Do you know how to add the yellow highlight effect of this 538 graph for both text and graphs using ggplot2?
Thanks in advance!
Update after clarification
It really depends on the structure of the data and what you are using to plot. However, if you wanted to add large highlights to particular plots, then you could plot the same geom_line but change the aesthetics of it (though the highlight will not connect to adjacent plots).
library(ggplot2)
hlines <- mtcars %>%
group_by(cyl) %>%
summarise(MN = min(wt))
ggplot(mtcars) +
geom_line(aes(mpg, wt), colour = "lightyellow", size = 80) +
geom_line(aes(mpg, wt)) +
geom_hline(
data = hlines,
aes(yintercept = MN),
linetype = "dotted",
color = "grey",
size = 1.5
) +
facet_wrap( ~ cyl) +
theme_bw()
Output
For text, in ggplot2, you can add fill to the background of annotations. But it again really depends on the structure and how you are plotting the text. You could split up the annotations, so that you could fill one and not the other part of the text.
ggplot(mtcars) +
geom_line(aes(mpg, wt), colour = "lightyellow", size = 80) +
geom_line(aes(mpg, wt)) +
annotate(
geom = "text",
x = 30,
y = 5,
label = "It hasn't really dropped off"
) +
annotate(
geom = "label",
x = 30,
y = 4.75,
label = "since he first won office in 2016",
fill = "lightyellow",
label.size = NA
)
Output
First Answer
It depends on what exactly you are looking for/what your data looks like. But if you are wanting to place a line at the minimum under a line graph in a faceted plot, then you could do something like this:
library(ggplot2)
hlines <- mtcars %>%
group_by(cyl) %>%
summarise(MN = min(wt))
ggplot(mtcars) +
geom_line(aes(mpg, wt)) +
geom_hline(
data = hlines,
aes(yintercept = MN),
linetype = "dotted",
color = "grey",
size = 1.5
) +
facet_wrap( ~ cyl) +
theme_bw()
Output
If you just have a single plot, then you can use geom_hline and just provide the y intercept.
ggplot(mtcars) +
geom_line(aes(mpg, wt)) +
geom_hline(yintercept = 3.5,
linetype = "dotted",
color = "grey",
size = 1.5
) +
theme_bw()
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")
I don't understand why the dots for ID 2,6,8,10 won't align vertically like they do in 1,3,4,7,9.
The offset is affected by stackratio, but why doesn't it affect all the groups?
ggplot(sleep,
aes(x=ID,fill=group,y=extra))+
geom_dotplot(binaxis = 'y',
method="histodot",
stackgroups = TRUE,
binpositions="bygroup",
stackratio=1,
binwidth=0.1,
stackdir = "center",
dotsize = 3)
Another example is
ggplot(mtcars, aes(x = factor(am),fill = factor(cyl), y = mpg)) +
geom_dotplot(binaxis = "y",stackgroups = TRUE, stackdir = "center", binpositions="all")
Here stackgroups = TRUE makes everything offset weirdly.
Can something be done here, or is there another way to get the samme?
It seems that geom_dotplot calculates "dodge" positions as if all the dots were in one group and then plots them in each group.
I found work around.
Here i make a plot and color the dots myself. This ggplot can not make a legend for, so I make another plot that was the right legend.
Then use plot_grid to make my final plot.
It is important to setkey right, or the plot will be colored incorrect.
mycars <- as.data.table(mtcars)
mycars[cyl=="4",mycol:="red"][cyl=="6",mycol:="green"][cyl=="8",mycol:="blue"]
setkey(mycars,am,mpg)
myplot <- ggplot(mycars, aes(x = factor(am), y = mpg)) +
geom_dotplot(binaxis = "y",
fill=mycars$mycol,
stackratio=1,
binwidth=0.7, drop=FALSE,
stackdir = "center",
dotsize = 1)
lplot <- ggplot(mtcars, aes(x = factor(am),fill = factor(cyl), y = mpg))+
geom_dotplot(binaxis = "y",stackgroups = TRUE)+
scale_fill_manual(values=c("red","green", "blue"))
mylegend <- get_legend(lplot)
plot_grid(myplot,mylegend,ncol=2,rel_widths = c(6,1))
Plot
I cannot tell you what's the issue when using the geom_dotplot function, but you can get what you want by using geom_point and the option position = position_dodge2(). Inside the function position_dodge2() you can use width to control the position of each point. See the full code below:
library(ggplot2)
ggplot(sleep,
aes(x=ID,fill=group,y=extra))+
geom_point(
size=3,
pch = 21,
position = position_dodge2(width=c(rep(0.00001,4),
0.2,
rep(0.00001,5)))
) +
scale_y_continuous(limits = c(-2,6)) +
theme_classic() +
theme(panel.grid.major.x = element_line(color="gray",
linetype = "dashed"))
The result:
Update
We can have different alignments within the same X. For instance, when ID=1 I can move the point for group 2 while maintaining the point for group 1:
Code:
library(ggplot2)
ggplot(sleep,
aes(x=ID,fill=group,y=extra))+
geom_point(
size=3,
pch = 21,
position = position_dodge2(width=c(0.7,
rep(0.00001,3),
0.2,
rep(0.00001,5),
0.00001,
rep(0.00001,3),
0.2,
rep(0.00001,5)))
) +
scale_y_continuous(limits = c(-2,6)) +
theme_classic() +
theme(panel.grid.major.x = element_line(color="gray",
linetype = "dashed"))
Taking the graph from ggplot2 help pages:
ggplot(mtcars, aes(factor(cyl))) + geom_bar() + facet_grid(. ~ vs)
Is it possible to change the border (colour and/or thickness) of only selected panels? I'd like to, for instance, change the border of the facet of '1' of faceting variable vs.
I tried adding
theme(panel.border = element_rect(size = 3, colour = "red", fill = NA))
but that solution changes all borders.
I was also thinking about using geom_rect or geom_polygon but am not sure how to limit it to one plot either.
I stumbled upon this thread on R help list, but the solutions didn't work for me
Any suggestions on how to move forward will be much appreciated.
How about filling it with a colour like this?
dd <- data.frame(vs = c(0,1), ff = factor(0:1))
ggplot() + geom_rect(data=dd, aes(fill=ff),
xmin=-Inf, xmax=Inf, ymin=-Inf, ymax=Inf, alpha=0.15) +
geom_bar(data = mtcars, aes(factor(cyl))) + facet_grid(. ~ vs) +
scale_fill_manual(values=c(NA, "red"), breaks=NULL)
I was trying to implement a facet border as well. I did just a little tweaking of the answer supplied by Hadley in the thread mentioned in the question as follows:
# Outline colours
outline <- data.frame(
cyl = c(4, 6, 8),
outline_color = c('green', 'orange', 'red')
)
# Points defining square region for background
square <- with(mtcars, data.frame(
x = c(-Inf, Inf, Inf, -Inf),
y = c(-Inf, -Inf, Inf, Inf)
))
ggplot(mtcars, aes(x = mpg, y = wt)) +
geom_polygon(aes(x = x,y = y, color = outline_color, fill = NA), data = merge(outline, square)) +
geom_point() +
scale_fill_identity() +
facet_grid(. ~ cyl)
Produces the following graph with differing facet borders: