How can I add annotation in ggplot like this? I need to add the text (CV, Network), the bars, and also those stars.
I hope you can transfer this example to your dataset:
ggplot() + geom_point(aes(x = 1:10, y = 1:10)) +
geom_segment(aes(x=0,y=11,xend=5,yend=11)) + geom_segment(aes(x=0,y=11,xend=0,yend=10.5)) + geom_segment(aes(x=5,y=11,xend=5,yend=10.5)) + ##bracket 1
geom_segment(aes(x=5.5,y=11,xend=10,yend=11)) + geom_segment(aes(x=5.5,y=11,xend=5.5,yend=10.5)) + geom_segment(aes(x=10,y=11,xend=10,yend=10.5)) + #bracket 2
geom_text(aes(x=2.5,y=11.5,label="Group 1")) + geom_text(aes(x=7.75,y=11.5,label="Group 2")) + #add labels
coord_cartesian(ylim = c(0, 10), clip="off")+theme(plot.margin = unit(c(4,1,1,0), "lines")) #change plot margins
Related
This is not my data (for confidentiality reasons), but I have tried to create a reproducible example using a dataset included in the ggplot2 library. I have an histogram summarizing the value of some variable by group (factor of 2 levels). First, I did not want the counts but proportions of the total, so I used that code:
library(ggplot2)
library(dplyr)
df_example <- diamonds %>% as.data.frame() %>% filter(cut=="Premium" | cut=="Ideal")
ggplot(df_example,aes(x=z,fill=cut)) +
geom_histogram(aes(y=after_stat(width*density)),binwidth=1,center=0.5,col="black") +
facet_wrap(~cut) +
scale_x_continuous(breaks=seq(0,9,by=1)) +
scale_y_continuous(labels=scales::percent_format(accuracy=2,suffix="")) +
scale_fill_manual(values=c("#CC79A7","#009E73")) +
labs(x="Depth (mm)",y="Count") +
theme_bw() + theme(legend.position="none")
It gave me this as a result.
enter image description here
The issue is that I would like to print the numeric percentages on top of the bins and haven't find a way to do so.
As I saw it done for printing counts elsewhere, I attempted to print them using stat_bin(), including the same y and label values as the y in geom_histogram, thinking it would print the right numbers:
ggplot(df_example,aes(x=z,fill=cut)) +
geom_histogram(aes(y=after_stat(width*density)),binwidth=1,center=0.5,col="black") +
stat_bin(aes(y=after_stat(width*density),label=after_stat(width*density*100)),geom="text",vjust=-.5) +
facet_wrap(~cut) +
scale_x_continuous(breaks=seq(0,9,by=1)) +
scale_y_continuous(labels=scales::percent_format(accuracy=2,suffix="")) +
scale_fill_manual(values=c("#CC79A7","#009E73")) +
labs(x="Depth (mm)",y="%") +
theme_bw() + theme(legend.position="none")
However, it does print way more values than there are bins, these values do not appear consistent with what is portrayed by the bar heights and they do not print in respect to vjust=-.5 which would make them appear slightly above the bars.
enter image description here
What am I missing here? I know that if there was no grouping variable/facet_wrap, I could use after_stat(count/sum(count)) instead of after_stat(width*density) and it seems that it would have fixed my issue. But I need the histograms for both groups to appear next to each other. Thanks in advance!
You have to use the same arguments in stat_bin as for the histogram when adding your labels to get same binning for both layers and to align the labels with the bars:
library(ggplot2)
library(dplyr)
df_example <- diamonds %>%
as.data.frame() %>%
filter(cut == "Premium" | cut == "Ideal")
ggplot(df_example, aes(x = z, fill = cut)) +
geom_histogram(aes(y = after_stat(width * density)),
binwidth = 1, center = 0.5, col = "black"
) +
stat_bin(
aes(
y = after_stat(width * density),
label = scales::number(after_stat(width * density), scale = 100, accuracy = 1)
),
geom = "text", binwidth = 1, center = 0.5, vjust = -.25
) +
facet_wrap(~cut) +
scale_x_continuous(breaks = seq(0, 9, by = 1)) +
scale_y_continuous(labels = scales::number_format(scale = 100)) +
scale_fill_manual(values = c("#CC79A7", "#009E73")) +
labs(x = "Depth (mm)", y = "%") +
theme_bw() +
theme(legend.position = "none")
I am currently plotting data using the ggpubr package in R (based on ggplot2). When I plot the means of two conditions including standard errors, the y-axis should be limited from 1 to 7, which I indicate using:
p <- ggline(data, x = "condition", y = "measure",
add = c("mean_se"),
ylab = "Measure")
ggpar(y, ylim = c(1, 7), ticks=T, yticks.by = 1)
In the final plot, however, the y-axis shows only values from 1 to 6
I tried to plot the same data using native ggplot2, but the problem persists, once I change the layout.
For ggplot2 I used:
p <- ggplot(data, aes(x=condition, y=measure)) +
geom_line() +
geom_point()+
geom_errorbar(aes(ymin=measure-se, ymax=measure+se), width=.2, position=position_dodge(0.05)) +
ylab("measure") +
xlab("Condition")
p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
p + theme_classic()
It would be great if someone could help me with this issue.
Edit:
as suggested in the comments, here is the data I am trying to plot using ggplot2:
structure(list(condition = structure(3:4, .Label = c("IC", "SC",
"ILC", "SLC"), class = "factor"), measure = c(4.10233918128655, 3.83040935672515
), se = c(0.235026318386523, 0.216811675834834)), class = "data.frame", row.names = c(NA,
-2L))
I think I got something resembling your plot with correct y-axes with the following code:
ggplot(data, aes(x = condition, y = measure)) +
geom_point() +
geom_errorbar(aes(ymin = measure-se, ymax = measure+se),
width = .2, position = position_dodge(0.05)) +
# Group prevents geom_line interpreting each x-axis point as it's own group
geom_line(aes(group = rep(1, nrow(data)))) +
xlab("Condition") +
# Expand is optional, it prevents padding beyond 1 and 7
scale_y_continuous(name = "measure",
limits = c(1, 7),
breaks = 1:7,
expand = c(0,0)) +
theme_classic()
The solution is much more trivial. You were doing everything right! Except for one clerical error. Here is what was happening:
First, you generate your initial plot, fine.
p <- ggplot(data, aes(x=condition, y=measure)) +
geom_line() + geom_point() +
geom_errorbar(aes(ymin=measure-se, ymax=measure+se),
width=.2, position=position_dodge(0.05)) +
ylab("measure") +
xlab("Condition")
This plot does not have the limits. When you add the limits and display it, the scales are correct:
p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
However, note that p did not change! You did not store the result of adding the limits to p. Therefore, p is still without the scale_y_continuous. No wonder then that when you type
p + theme_classic()
...the limits are gone. However, if you try
p <- p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
p + theme_classic()
everything will be correct.
I saw this answer but couldn't replicate it.
I get my data like this:
df = data.frame(x = rep(sample(letters, 4), 2),
y = round(runif(8,1,100),0),
z = c(rep("group1",4), rep("group2",4)))
# I then add a 'percent' column like so:
df$perc[1:4] = df$y[1:4] / sum(df$y[1:4])
df$perc[5:8] = df$y[5:8] / sum(df$y[5:8])
# Which I then convert like so:
df$perc = paste(round(df$perc * 100, 1), "%", sep="")
# The ggplot:
library(ggplot2)
ggplot(df) +
geom_bar(aes(z, y, fill=x), position="dodge", stat="identity") +
geom_text(aes(z,y,label=perc), position=position_dodge(width=1), size=4)
Result:
I can't figure out what I did wrong.
Just one minor change solves the issue. You need to specify group=x inside your geom_text(aes(...)) call.
ggplot(df) +
geom_bar(aes(z, y, fill=x), position=position_dodge(width=1), stat="identity") +
geom_text(aes(z,y,label=perc, group=x), position=position_dodge(width=1), size=4)
Thi is my data:
x <- c("22-01-16","26-01-16","28-01-16","01-02-16","05-02-16","16-02-16","17-03-16","18-03-16","04-04-16","05-04-16","06-04-16","08-04-16")
y <- c(97.14,75,54.44,70.45,110.56,66.3,178.76,171.90,419.41,424,518.63,242.17)
z <- c("ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP","ADCP")
So I make the dataframe
Datos <- data.frame(x)
Datos$Caudal <- y
Datos$Tipo <- z
Datos$Fecha <- as.Date(Datos$x, "%d-%m-%y")
and plot using ggplot2
Serie_Caudal <-
ggplot(Datos, aes(Fecha, Caudal)) +
geom_line(size=1, colour="red") +
geom_point(shape=23,size=1, colour="blue",fill = "blue") +
scale_x_date(date_breaks = "1 week",labels = date_format("%d/%b"))+
xlab("Fecha") + ylab(bquote('Caudal ('*m^3~s^-1*')')) +
ggtitle("Caudales Diarios (01-06/2016)")
Serie_Caudal
I try to plot a legend but i can´t the way, i try use Melt but my data change in a way i can´t plot. Also try scale_fill_manual but the legend don´t show up. I want to know if there is a way to put a legend manualy.
The legend must show a blue point and ADCP
This shows only a blue dot.
ggplot(aes(Fecha, Caudal, colour = "ADCP"), data = Datos) +
geom_point() +
geom_point(shape=23,size=1,color="blue",fill = "blue") +
scale_color_manual(values = c("ADCP"="blue"),name = "") +
geom_line(color="red", size=1) +
scale_x_date(date_breaks = "1 week",labels = date_format("%d/%b")) +
xlab("Fecha") + ylab(bquote('Caudal ('*m^3~s^-1*')')) +
ggtitle("Caudales Diarios (01-06/2016)")
I made the following plot in Excel:
But then I thought I would make it prettier by using ggplot. I got this far:
If you're curious, the data is based on my answer here, although it doesn't really matter. The plot is a standard ggplot2 construct with some prettification, and the thick line for the x-axis through the middle is achieved with p + geom_hline(aes(yintercept=0)) (p is the ggplot object).
I feel that the axis configuration in the Excel plot is better. It emphasizes the 0 line (important when the data is money) and finding intercepts is much easier since you don't have to follow lines from all the way at the bottom. This is also how people draw axes when plotting on paper or boards.
Can the axis be moved like this in ggplot as well? I want not just the line, but the tick labels as well moved. If yes, how? If no, is the reason technical or by design? If by design, why was the decision made?
try this,
shift_axis <- function(p, y=0){
g <- ggplotGrob(p)
dummy <- data.frame(y=y)
ax <- g[["grobs"]][g$layout$name == "axis-b"][[1]]
p + annotation_custom(grid::grobTree(ax, vp = grid::viewport(y=1, height=sum(ax$height))),
ymax=y, ymin=y) +
geom_hline(aes(yintercept=y), data = dummy) +
theme(axis.text.x = element_blank(),
axis.ticks.x=element_blank())
}
p <- qplot(1:10, 1:10) + theme_bw()
shift_axis(p, 5)
I tried to change the theme's axis.text.x,but only can change hjust.
So I think you can delete axis.text.x,then use geom_text() to add.
For example:
test <- data.frame(x=seq(1,5), y=seq(-1,3))
ggplot(data=test, aes(x,y)) +
geom_line() +
theme(axis.text.x=element_blank(), axis.ticks.x=element_blank()) +
geom_text(data=data.frame(x=seq(1,5), y=rep(0,5)), label=seq(1,5), vjust=1.5)
Maybe these codes are useful.
just to complete baptiste's excellent answer with the equivalent for moving the y axis:
shift_axis_x <- function(p, x=0){
g <- ggplotGrob(p)
dummy <- data.frame(x=x)
ax <- g[["grobs"]][g$layout$name == "axis-l"][[1]]
p + annotation_custom(grid::grobTree(ax, vp = grid::viewport(x=1, width = sum(ax$height))),
xmax=x, xmin=x) +
geom_vline(aes(xintercept=x), data = dummy) +
theme(axis.text.y = element_blank(),
axis.ticks.y=element_blank())
}
As alistaire commented it can be done using geom_hline and geom_text as shown below.
df <- data.frame(YearMonth = c(200606,200606,200608,200701,200703,200605),
person1 = c('Alice','Bob','Alice','Alice','Bob','Alice'),
person2 = c('Bob','Alice','Bob','Bob','Alice','Bob'),
Event = c('event1','event2','event3','event3','event2','event4')
)
df$YM <- as.Date(paste0("01",df$YearMonth), format="%d%Y%m")
rangeYM <- range(df$YM)
ggplot()+geom_blank(aes(x= rangeYM, y = c(-1,1))) + labs(x = "", y = "") +
theme(axis.ticks = element_blank()) +
geom_hline(yintercept = 0, col = 'maroon') +
scale_x_date(date_labels = '%b-%y', date_breaks = "month", minor_breaks = NULL) +
scale_y_continuous(minor_breaks = NULL) +
geom_text(aes(x = df$YM, y = 0, label = paste(format(df$YM, "%b-%y")), vjust = 1.5), colour = "#5B7FA3", size = 3.5, fontface = "bold")