Is there a way to use the distance between the ticks in the y-axis as variable within ggplot function?
I want to plot an annotation whose y-coordinate can be "responsive" to the y-axis scale of a graph.
In the example below, I would like var1 to be the distance between successive y-axis ticks as taken from the parameters of the specific graph, and not a user-defined constant.
Data:
EXse2<- data.frame(wk=c(1,2), EX=c(4.457143, 2.580952), se=c(0.4209481,0.5519333))
Code:
var1<- 0.1
labEX<- "\u002A\u002A"
library(ggplot2)
ggplot(EXse2, aes(x=factor(wk), y=EX, group=1))+
geom_errorbar(aes(ymin=EX-se, ymax=EX+se), width=.2, size=1)+
geom_line(size=1)+
geom_point(size=2)+
annotate("text", label=labEX, x=1.5, y=(mean(EXse2$EX[1:2])+var1))+
xlab("period")+
ylab(expression(bar(EX)))+
theme(
panel.background=element_blank(),
panel.border = element_blank(),
panel.grid.minor.x=element_blank(),
panel.grid.major.x=element_blank(),
panel.grid.minor.y = element_line(colour = "#d9d9d9"),
panel.grid.major.y = element_line(colour = "#bfbfbf"),
axis.line = element_line()
)
You can achieve this by creating to plot first, extracting the tick distances with ggplot_build and then add the annotation:
library(ggplot2)
EXse2<- data.frame(wk=c(1,2), EX=c(4.457143, 2.580952), se=c(0.4209481,0.5519333))
labEX<- "\u002A\u002A"
#first, put your plot in p1
p1 <-
ggplot(EXse2, aes(x=factor(wk), y=EX, group=1))+
geom_errorbar(aes(ymin=EX-se, ymax=EX+se), width=.2, size=1)+
geom_line(size=1)+
geom_point(size=2)+
# I HAVE REMOVED THE ANNOTATE HERE
xlab("period")+
ylab(expression(bar(EX)))+
theme(
panel.background=element_blank(),
panel.border = element_blank(),
panel.grid.minor.x=element_blank(),
panel.grid.major.x=element_blank(),
panel.grid.minor.y = element_line(colour = "#d9d9d9"),
panel.grid.major.y = element_line(colour = "#bfbfbf"),
axis.line = element_line()
)
# extract axis limits
yminticks <- ggplot_build(p1)$panel$ranges[[1]]$y.minor_source
# subtract first tick from second
var1 <- yminticks[2] - yminticks[1]
# and now add the annotate and plot
p1 +
annotate("text", label=labEX, x=1.5, y=(mean(EXse2$EX[1:2])+var1))
Related
I have 4 graphs that are similar to this one (just use a different dataframe (don, don1, don2). I want to combine them in one graph with the line colors designated as the dataframe with a common legend.
ggplot(don, aes(x=poscum, y=pval)) +
# Show all points
geom_line() +
# custom X axis:
scale_x_continuous( label = axisdf$CHR, breaks= axisdf$center ) +
scale_y_continuous(expand = c(0, 0) ) + # remove space between plot area
and x axis
# Custom the theme:
theme_bw() +
theme(
legend.position="none",
panel.border = element_blank(),
panel.grid.major = element_line(colour="white"),
panel.grid.minor = element_line(colour="white"),
axis.ticks = element_line(colour = "black"),
axis.line = element_line(colour = "black"),
)
You can use facets for this. Like so:
donall <- data.frame(rbind(don, don1, don2), group= rep("don", nrow(don)), rep("don1", nrow(don1)), rep("don2", nrow(don2)))
ggplot(donall, aes(x=poscum, y=pval)) +
geom_line()+
facet_wrap(~group, ncol=2) +....
I am trying to make a stacked and grouped barplot using the following datasets:
dfplot <- data.frame(organisms=c("M.musculus","D.melanogaster" ,"H.sapiens","O.sativa","S.pombe","C.familiaris",
"G.gallus","P.falciparum","A.thaliana","C.elegans","D.rerio","B.taurus","S.cerevisiae","R.norvegicus","C.intestinalis","B.subtilis","E.coli"),
KEGGv2=c(20,7,21,126,106,62,26,80,5,5,13,306,8,35,32,104,107),
KEGGv1=c(286,124,289,0,0,244,135,0,121,124,148,0,101,271,87,0,0),
Reactome=c(358,146,596,115,54,306,370,23,155,112,365,341,52,364,0,0,0))
# Melt the dataframe
melted <- melt(dfplot, "organisms")
# Reformat the data labels
melted$cat <- ''
melted[melted$variable == 'Reactome',]$cat <- "Reactome"
melted[melted$variable != 'Reactome',]$cat <- "KEGG"
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~ organisms)+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
strip.text.x = element_blank(),
strip.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line = element_line(colour = "black"))
And my output is the following one:
I used a facet_grid per organism because I wanted to have a mix between stack (for both KEGGv1 and KEGGv2) and then group it with the other group Reactome. However, when doing the melting, the x-axis will have two labels per facet_grid (KEGG and Reactome, which is the variable obtained from the melting [cat]). I did not want that label so I remove them.
What I am trying to do is to have the organism name per each of the groupings, so each of the 17 grouping bars will have the name of the corresponding organism**. Therefore, I am missing that, I have tried several ways but I cannot find the proper way of doing it.
Thanks in advance,
You can do two things to make this work:
Rotate the labels of the facet so that they plot at 90 degrees
Plot the facet labels beneath the graph using the switch = 'x' argument within facet_grid.
Here is the complete example:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
facet_grid(~organisms, switch = 'x')+
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.y = element_line(colour = "black"),
strip.text = element_text(angle = 90))
I left the default shaded background, but you can easily style as you prefer.
Aproach Two
You might want to consider rotating the plot. This requires you to flip the coordinates of the plot using coord_flip before the facet is called. As we are faceting in the other direction we change the facet argument to facet_grid(organisms~.). All other arguments which refer to x or y are swapped over:
ggplot(melted, aes(x=cat, y=value, fill=variable)) +
geom_bar(stat = 'identity', position = 'stack') +
coord_flip() +
facet_grid(organisms~., switch = 'y') +
scale_fill_manual(values=c("deepskyblue4", "lightblue1", "olivedrab2")) +
labs(y = "Number of Pathways") +
theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
legend.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank(),
axis.line.x = element_line(colour = "black"),
strip.text.y = element_text(angle = 180))
First you can set the organism labels to be below the bars, rather than above. This is established by setting the switch argument of the facet_grid function to "x" (see code below). Secondly, you should then remove axis.title.x=element_blank() argument within your theme function call. The updated code is below. Hope this helps!
ggplot(melted, aes(x = cat, y = value, fill =variable)) +
geom_bar(stat = 'identity', position = 'stack') +facet_grid(~organisms, switch="x")+
scale_fill_manual(values=c("deepskyblue4","lightblue1","olivedrab2"))+
ylab("Number of pathways")+
theme(axis.title.x=element_blank(),axis.text.x=element_blank(),axis.ticks.x=element_blank())+theme(legend.title=element_blank())+
theme(strip.background = element_blank())+theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),panel.background = element_blank(), axis.line = element_line(colour = "black"))
I want to make a plot (ggplot) with a date x axis, where the x axis is at y=0, but the x labels are at the bottom. It should look more or less like the graph in this picture:
I tried it with hline like this:
ggplot(coe_melt, aes(x=time, y=value, color=score))+
geom_hline(yintercept=0)+
geom_line(size=2)+
scale_color_manual(values=c('blue','magenta','red','green'), breaks=c('Profitability', 'Growth', 'Safety','Payout'))+
theme_bw()+
theme(legend.position = 'bottom')+
theme(axis.ticks.x = element_blank())
I read in several threads that it can be done with scale_x_continuous(), but the problem is that my x axis contains dates and not numbers. When I tried it with scale_x_continous() I got an error (origin not supplied). I tried it with scale_x_date, but I didn't manage to get the result.
With the code above I get the following plot:
In the end I want a horizontal line/axis with ticks at y=0, I want to remove the "lower x axis" and additionally I would like to have "tight" axes (like in the first picture).
My data looks like this:
> head(coe_melt)
time score value
1 1977-07-01 Profitability 0.4737371
2 1978-07-01 Profitability 0.4918117
3 1979-07-01 Profitability 0.4249600
4 1980-07-01 Profitability 0.3847234
5 1981-07-01 Profitability 0.3604534
6 1982-07-01 Profitability 0.4012554
> coe_melt[c(1,40,79,118),]
time score value
1 1977-07-01 Profitability 0.47373711
40 1977-07-01 Growth 0.51024065
79 1977-07-01 Safety 0.02525786
118 1977-07-01 Payout -0.12501210
See my answer below
ggplot(coe_melt, aes(x=time, y=value, color=score))+
geom_hline(yintercept=0)+
geom_line(size=2)+
scale_color_manual(values=c('blue','magenta','red','green'),
breaks=c('Profitability', 'Growth', 'Safety','Payout'))+
theme_bw()+
theme(legend.position = 'bottom')+
theme(axis.ticks.x = element_blank())+
theme(plot.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank() )+
theme(panel.border= element_blank())+
theme(axis.line.y = element_line(color="black", size = 0.5))+
expand_limits(y=c(-0.4, 0.8))+
scale_y_continuous(breaks=seq(-0.4, 0.8, 0.2))
With a combination of the answer of Al14 and the answer of baptiste from the linked (similar) question provided by Axeman, I managed to get pretty close to the wished result with the following code:
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.ticks.x=element_blank())+
theme(axis.line.y = element_line(color='black'), axis.text.x = element_blank(), legend.title=element_blank(),
plot.background = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), panel.border= element_blank())
}
colo2 <- c("#E41A1C", "#984EA3", "#377EB8", "#4DAF4A")
p <- ggplot(coe_melt, aes(x=time, y=value, color=score))+geom_line(size=2)+
scale_color_manual(values=colo2, breaks=c('Profitability', 'Growth', 'Safety','Payout'))+
theme_bw()+theme(legend.position = 'bottom', axis.title.x = element_blank(), axis.title.y = element_blank())+
scale_x_date(limit=as.Date(c('1977-07-01', '2015-07-01')), expand=c(0,0))
shift_axis(p, 0)
For me that's close enough, thanks for your help everybody ;)
Hi I have the plot below and the marginal density plots are slightly off. They do not line up to the x and y axis of the scatter plot so interpretation can be a bit misleading.
I can sort of play with these lines of code to try and get the margins to align for rthe marginal plots but it is very manual and frustrating.
theme0(plot.margin = unit(c(1,0,0,2.2),"lines"))
theme0(plot.margin = unit(c(0,1,1.2,0),"lines"))
Is there a way to automatically find the right margins to pass to theme0(plot.margin = unit(c(0,1,1.2,0),"lines") so that no manual work needs to be done to line up the margins? Thank you.
library(ggplot2)
library(gridExtra)
set.seed(42)
DF <- data.frame(x=rnorm(100,mean=c(1,5)),y=rlnorm(100,meanlog=c(8,6)),group=1:2)
DF
## Scatter plot
p1 <- ggplot(DF,aes(x=x,y=y)) + geom_point() +
scale_x_continuous(expand=c(0.02,0)) +
scale_y_continuous(expand=c(0.02,0)) +
theme_bw() +
theme(legend.position="none",plot.margin=unit(c(0,0,0,0),"points")) # ggplot(DF,aes(x=x,y=y,colour=factor(group))) color the gorup
theme0 <- function(...) theme( legend.position = "none",
panel.background = element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.margin = unit(0,"null"),
axis.ticks = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.ticks.length = unit(0,"null"),
axis.ticks.margin = unit(0,"null"),
panel.border=element_rect(color=NA),...)
### DENSITY OF X
p2 <- ggplot(DF,aes(x=x, fill="blue")) +
geom_density(alpha=0.5) +
scale_x_continuous(breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(1,0,0,2.2),"lines")) # to color group ggplot(DF,aes(x=x,colour=factor(group),fill=factor(group)))
### DENSITY OF Y
p3 <- ggplot(DF,aes(x=y, fill = "red")) +
geom_density(alpha=0.5) +
coord_flip() +
scale_x_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
scale_y_continuous(labels = NULL,breaks=NULL,expand=c(0.02,0)) +
theme_bw() +
theme0(plot.margin = unit(c(0,1,1.2,0),"lines")) # color group ggplot(DF,aes(x=y,colour=factor(group),fill=factor(group)))
grid.arrange(arrangeGrob(p2,ncol=2,widths=c(3,1)),
arrangeGrob(p1,p3,ncol=2,widths=c(3,1)),
heights=c(1,3))
I have a plot in ggplot:
ggplot(plot1,aes(x=c,y=value,colour=variable,linetype=variable,size=variable)) +
geom_line() +
scale_x_continuous(breaks=seq(1,10,1)) +
scale_y_continuous(breaks=seq(0,1, 0.1))+
scale_colour_manual(values=rep(c("blue3","red3"),each=9)) +
scale_linetype_manual(values = rep(c(3,1),each=9)) +
scale_size_manual(values = rep(c(0.6,0.3),each=9)) +
theme_bw(base_size=12, base_family="Helvetica") +
theme(axis.text=element_text(size=8),
axis.title=element_text(size=8),
text = element_text(size=14),
axis.line = element_line(size=0.25),
axis.ticks=element_line(size=0.25),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
legend.position="none" ,
legend.direction="vertical",
legend.title=element_blank(),
legend.text=element_text(size=8),
legend.background=element_blank(),
legend.key=element_blank())+labs(title='a',x='b', y='c' )+theme(plot.title=element_text(size=8))+theme(plot.margin=unit(c(0.1,0,0.1,0),"cm"))
I would like to disable:
the numbers on the y axis
the small lines indicating the position of the numbers
the label
Is this possible to do without affecting the x axis?
I think you can use this approach.
p1 + theme(axis.text.y=element_blank())+ylab("") + scale_y_discrete(breaks=NULL)
# p1 = your initial graph
# axis.text.y removes number
# ylab("") removes y label
# scale_y_discrete(breaks=NULL) removes the tick marks. Your x-axis will not be affected.
Good luck.
You can also do everything in the theme() part of your code. Just add the following code:
p1 + theme(axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank())