Related
After looking at various post and asking questions here i have been able to make a multi faceted pie chart. But i am facing a problem in tidying up the pie chart. Here are the things i am having troubles with:
How do i remove the facet labels from each row and only have one facet label on the top or bottom and left or right? How do i control how the facet label looks?
I have tried using facet_grid instead of facet_wrap and that removes the label from each row but still the labels are inside a box. I would like to remove the box which i donot seem to be able to do.
Centering the labels so that the values for each fraction of the pie is inside that pie-slice.
Some of my piechart have 8 to 10 values and they are not always inside there fraction. First i used geom_text_repel but that only helped me to repel the text. It didnt place the text inside each fraction. I also looked at this thread. I tried that by creating a new dataframe which has a position values and using that pos inside geom_text like so d<-c %>% group_by(Parameter)%>% mutate(pos= ave(Values, Zones, FUN = function(x) cumsum(x) - 0.5 * x)) and using the same code to make pie chart for d dataframe but it didnt quite work.
Grouping the values under certain level into one single "other" groups so the number of slices would be less
It would be ideal for me to be able to group the values with less than 1 % into one single group and call it "others" so that the number of slices are less. So far i have to completely ignore those values by c<-c[c$Values>1,] and using this newly created data frame.
Any suggestions/help regarding these issues would be helpful.
Following is the reproducible example of my current pie chart:
library(RColorBrewer)
library(ggrepel)
library(ggplot2)
library(tidyverse)
my_pal <- colorRampPalette(brewer.pal(9, "Set1"))
#### create new matrix ############
new_mat<-matrix(, nrow=40, ncol = 4)
colnames(new_mat)<-c("Zones", "ssoilcmb", "Erosion_t", "area..sq.m.")
for ( i in 1:nrow(new_mat)){
new_mat[i,4]<-as.numeric(sample(0:20, 1))
new_mat[i,3]<-as.numeric(sample(0:20, 1))
a<-sample(c("S2","S3","S4","S5","S1"),1)
b<-sample(c("Deep","Moderate","Shallow"),1)
new_mat[i,1]<-sample(c("High Precip","Moderate Precip","Low Precip"),1)
new_mat[i,2]<-paste0(a,"_",b)
}
m_dt<-as.data.frame(new_mat)
m_dt$Erosion_t<-as.numeric(m_dt$Erosion_t)
m_dt$area..sq.m.<-as.numeric(m_dt$area..sq.m.)
#### calculate parea
m_dt<- m_dt %>%
group_by(Zones)%>%
mutate(per_er=signif((`Erosion_t`/sum(`Erosion_t`))*100,3), per_area=signif((`area..sq.m.`/sum(`area..sq.m.`))*100,3))
## Rearranging data:
a<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_er)
b<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_area)
c<-data.frame(Zones=m_dt$Zones,ssoilcmb=m_dt$ssoilcmb,
Parameter=c(rep("Erosion",40),rep("Area",40)),
Values=c(m_dt$per_er,m_dt$per_area))
### New Plot ###
ggplot(c, aes(x="", y=Values, fill=ssoilcmb)) +
geom_bar(stat="identity", width=1, position = position_fill())+
coord_polar("y", start=0) +
facet_wrap(Zones~Parameter, nrow = 3) +
geom_text_repel(aes(label = paste0(Values, "%")), position = position_fill(vjust = 0.5))+
scale_fill_manual(values=my_pal(15)) +
labs(x = NULL, y = NULL, fill = NULL, title = "Erosions")+
theme_classic() + theme(axis.line = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, color = "#666666"))
If you're open to alternatives, maybe a facet_wrapped barplot will suit your needs, e.g.
library(RColorBrewer)
library(ggrepel)
library(tidyverse)
my_pal <- colorRampPalette(brewer.pal(9, "Set1"))
#### create new matrix ############
new_mat<-matrix(nrow=40, ncol = 4)
colnames(new_mat)<-c("Zones", "ssoilcmb", "Erosion_t", "area..sq.m.")
for ( i in 1:nrow(new_mat)){
new_mat[i,4]<-as.numeric(sample(0:20, 1))
new_mat[i,3]<-as.numeric(sample(0:20, 1))
a<-sample(c("S2","S3","S4","S5","S1"),1)
b<-sample(c("Deep","Moderate","Shallow"),1)
new_mat[i,1]<-sample(c("High Precip","Moderate Precip","Low Precip"),1)
new_mat[i,2]<-paste0(a,"_",b)
}
m_dt<-as.data.frame(new_mat)
m_dt$Erosion_t<-as.numeric(m_dt$Erosion_t)
m_dt$area..sq.m.<-as.numeric(m_dt$area..sq.m.)
#### calculate parea
m_dt<- m_dt %>%
group_by(Zones)%>%
mutate(per_er=signif((`Erosion_t`/sum(`Erosion_t`))*100,3),
per_area=signif((`area..sq.m.`/sum(`area..sq.m.`))*100,3))
## Rearranging data:
a<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_er)
b<-data.frame(m_dt$Zones,m_dt$ssoilcmb, m_dt$per_area)
c<-data.frame(Zones=m_dt$Zones,ssoilcmb=m_dt$ssoilcmb,
Parameter=c(rep("Erosion",40),rep("Area",40)),
Values=c(m_dt$per_er,m_dt$per_area))
### New Plot ###
c$Zones <- factor(c$Zones,levels(c$Zones)[c(2,3,1)])
ggplot(c, aes(x=ssoilcmb, y=Values, fill=ssoilcmb)) +
geom_col()+
facet_wrap(Zones~Parameter, nrow = 3) +
scale_fill_manual(values=my_pal(15)) +
labs(x = NULL, fill = NULL, title = "Erosions")+
theme_minimal() + theme(axis.line = element_blank(),
axis.ticks = element_blank(),
axis.text.x = element_text(angle = 90,
hjust = 1,
vjust = 0.5),
plot.title = element_text(hjust = 0.5,
color = "#666666"))
I'm having some issues with ggplot2 and y axis tick marks - if someone can provide any input I'd really appreciate it.
I'm trying to create a 'stacked' plot with independent y axis for publication I'm working on. The idea is to have N plots stacked with a common X axis but distinct Y axes for each subplot while making it seem like a single contiguous plot.
I would like inverted tick marks on the x axis (for the bottom most subplot) and all the y axes. Problem is while the tick marks show up on the yaxis breifly in the plot generation they seem to be overwritten at the last stage and become invisible. Its such a minor thing and I could just leave them off but I'd really like to know what is going on for my own sanity...
Below is some sample code that should reproduce the problem and here is an imgur link highlighting the plot style and missing tick marks.
On a tangent, if anyone knows how to customize the axis.line.y.right / axis.line.x.top without using a dummy 'second axis' let me know (it seems a very verbose way of doing something that should be simple).
Thanks for your help
ylim=c(-5,5)
xlim=c(3,12)
ybreaks=c(-2,2)
base <- ggplot() +
theme_bw() +
scale_y_continuous(limits=ylim, breaks=ybreaks) +
scale_x_continuous(limits=xlim) +
labs(x="", y="") +
theme( panel.grid.major=element_line("gray78",0.5,1),
panel.border=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_text(margin=unit(c(0,3,0,0), "mm")))
bottom <- base + xlab("xlab") +
theme( axis.ticks.length.y=unit(-2,"mm"),
axis.ticks.length.x=unit(-2,"mm"),
axis.line.y=element_line(),
axis.line.x=element_line(),
plot.margin=unit(c(0,5,5,5),"mm"),
axis.text.x=element_text(margin=unit(c(3,0,0,0), "mm")))
middle <- base +
theme( axis.ticks.length.y=unit(-2,"mm"),
axis.ticks.length.x=unit(0,"mm"),
axis.line.y=element_line(),
axis.line.x=element_line(linetype=3),
plot.margin=unit(c(0,5,0,5),"mm"),
axis.title=element_blank())
top <- base +
theme( axis.ticks.length.y=unit(-2,"mm"),
axis.ticks.length.x=unit(0,"mm"),
axis.line.y=element_line(),
axis.line.x=element_line(linetype=3),
plot.margin=unit(c(5,5,0,5),"mm"),
axis.title=element_blank())
ggarrange(top,middle,bottom,ncol=1)
The easiest and more ggplot-y way would be to use facets.
I recommend using labs(x=NULL, y=NULL), because using = '' actually is drawing something.
I am removing the facet strips in the plot, but I generally think your graph may be slightly less confusing when you keep the labels and also keep a bit of distance between those graphs.
In order to add the dashed lines between your facets, you could simply add annotations, e.g., with annotate(geom = 'segment')
library(ggplot2)
ylim=c(-5,5)
xlim=c(3,12)
ybreaks=c(-2,2)
ggplot(data.frame(facet = letters[1:3])) +
theme_bw() +
annotate(geom = 'segment', x = -Inf, xend = Inf, y = -Inf, yend = -Inf, linetype = 3)+
scale_y_continuous(limits=ylim, breaks=ybreaks) +
scale_x_continuous(limits=xlim) +
labs(x=NULL, y=NULL) +
theme( panel.grid.major=element_line("gray78",0.5,1),
panel.border=element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_text(margin=unit(c(0,3,0,0), "mm")),
panel.spacing = unit(0, "lines"),
strip.background = element_blank(),
strip.text = element_blank(),axis.line.y=element_line(),
axis.line.x=element_line(),
axis.ticks.length.y=unit(-2,"mm"),
axis.ticks.length.x=unit(-2,"mm"),
plot.margin=unit(c(b = 5, t = 5, r = 5, l = 5),"mm")) +
facet_wrap(~facet, nrow = 3)
Created on 2020-02-22 by the reprex package (v0.3.0)
I have to arrange two plots with same axes next to each other and did this with ggplot2 and grid.arrange. Because of a more tidy representation, the legends have to be placed bottom. Unfortunately some times the left plot has more legend entries than the right one and therefore needs a second line, yielding x-axes on different y positions. Therefore it does not only look untidy, the aim of being able to compare these plots is not fulfilled anymore.
Can anybody help?
plot_left <- some_ggplot2_fct(variable,left) +
theme(legend.position = "bottom")+
theme(legend.background = element_rect(size = 0.5, linetype="solid", colour ="black"))
plot_right <- some_ggplot2_fct(variable,right,f)+
theme(legend.position = "bottom")+
theme(legend.background = element_rect(size = 0.5, linetype="solid", colour ="black"))
# adjust y axis for more easy compare
upper_lim <- max(plot_Volume_right$data$value, plot_Volume_left$data$value)
lower_lim <- min(plot_Volume_right$data$value, plot_Volume_left$data$value)
plot_Volume_left <- plot_Volume_left + ylim(c(lower_lim, upper_lim))
plot_Volume_right <- plot_Volume_right + ylim(c(lower_lim, upper_lim))
# Arrange plots in grid
grid.arrange(plot_Volume_left, plot_Volume_right,
ncol = 2,
top = textGrob(strTitle,
gp = gpar(fontfamily = "Raleway", fontsize = 15, font = 2)))
In the picture you can see the result:
Do you now an easy way to solve this without too much change in code? (The underlying framework is quite large)
I am attempting to make a facet_wrap bar_graph with error bars (se) that clearly shows three different categorical variables (Treatment, Horizon, Enzyme) with one response variable (AbundChangetoAvgCtl). Below is the code for some dummy data followed by the ggplot code I have so far. The graphs I've made can be see at this link:
bargraph figures
Enzyme <- c("Arabinosides","Arabinosides","Arabinosides","Arabinosides","Arabinosides","Arabinosides","Cellulose","Cellulose","Cellulose","Cellulose","Cellulose","Cellulose","Chitin","Chitin","Chitin","Chitin","Chitin","Chitin","Lignin","Lignin","Lignin","Lignin","Lignin","Lignin")
Treatment <- c("Deep","Deep","Int","Int","Low","Low","Deep","Deep","Int","Int","Low","Low","Deep","Deep","Int","Int","Low","Low","Deep","Deep","Int","Int","Low","Low")
Horizon <- c("Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min","Org","Min")
AbundChangetoAvgCtl <- rnorm(24,mean=0,sd=1)
se <- rnorm(24, mean=0.5, sd=0.25)
notrans_noctl_enz_toCtl_summary <- data.frame(Enzyme,Treatment,Horizon,AbundChangetoAvgCtl,se)
ggplot(notrans_noctl_enz_toCtl_summary, aes(x=Horizon, y=AbundChangetoAvgCtl, fill=Horizon, alpha=Treatment)) +
geom_bar(position=position_dodge(), colour="black", stat="identity", aes(fill=Horizon)) +
geom_errorbar(aes(ymin=AbundChangetoAvgCtl-se, ymax=AbundChangetoAvgCtl+se),
width=.2,
position=position_dodge(.9)) +
scale_fill_brewer(palette = "Set1") + theme_bw() +
geom_hline(yintercept=0) +
labs(y = "Rel Gene Abundance Change / Control", x="") +
theme(axis.ticks = element_blank(),
axis.text.x = element_blank(),
strip.text.x = element_text(size=20),
plot.title = element_text(size=22, vjust=2, face="bold"),
axis.title.y = element_text(size=18),
legend.key.size = unit(.75, "in"),
legend.text = element_text(size = 15),
legend.title = element_text(size = 18)) +
facet_wrap(~Enzyme, scales="free")
(figure 1)
So this is close to what I want, however for some reason, the "alpha=Treatment" call in ggplot causes my errorbars to fade (which I don't want) as well as the bar_fill (which I do want). I've tried moving the "alpha=Treatment" to the geom_bar call, as well as adding "alpha=1" to geom_bar, but when I do that, the error bars all move to a single location and overlap (figure 2).
I initially wanted to cluster the bars within facet_wrap, but found the alpha option on this site, which seems to accomplish what I'm looking for as well. Any help would be appreciated. If there is a better way to represent all of this, those ideas are welcome as well.
Also, if there is a way to condense and clarify my legend, that would be extra bonus!
Thanks in advance for your help!
Mike
You need to assign Treatment to the group option in the ggplot() command and then move the alpha=Treatment option to the geom_bar() command. Then the alpha value of geom_errorbar won't be affected by the global option and will be black. Like this:
ggplot(notrans_noctl_enz_toCtl_summary, aes(x=Horizon, y=AbundChangetoAvgCtl, fill=Horizon, group = Treatment)) +
geom_bar(position=position_dodge(), colour="black", stat="identity", aes(fill=Horizon, alpha = Treatment))
Also, I would check whether setting alpha=Treatment corresponds to more transparent as being equivalent to low treatment and less transparent to high treatment. At least that would be my intuitive understanding, without any background on the research design or data.
For information about formatting legends, see here.
Here is my data (called "data" and is a CSV format file):
attitude,order,min,max,mean,SpRate
Commanding,7,0.023005096,1.6517,0.681777825,5.66572238
Friendly,10,0.20565908,1.7535,0.843770095,6.191950464
Hostile,12,0.105828885,2.4161,1.128603777,6.493506494
Insincere,1,0.110689225,1.5551,0.730545923,5.115089514
Irony,4,0.089307133,2.2395,0.955312553,5.249343832
Joking,2,0.165717303,2.1871,0.94512688,5.141388175
Neutral,5,-0.044620705,1.5322,0.696879247,5.420054201
Polite,11,0.170151929,1.8467,0.873735105,6.191950464
Praising,8,0.192402573,2.0631,0.972857404,5.797101449
Rude,13,0.249746688,2.2885,1.100819511,6.644518272
Serious,6,0.011312206,1.7195,0.693606814,5.649717514
Sincere,9,-0.09135461,1.6409,0.659525513,5.813953488
Suggesting,3,0.072541529,1.8345,0.82999014,5.249343832
Here is my code:
library(ggplot2)
ggplot (data, aes(x=order))+
geom_rect(aes(xmin=order-0.1, xmax=order+0.1, ymin = min, ymax=max), size=1, alpha=0,color="black")+
geom_bar(aes(y=SpRate, fill="SpRate"),stat="identity", alpha=0.2, width=0.9)+
geom_point(aes(y=min, shape="min"), size=5, fill="white")+
geom_point(aes(y=mean, shape="mean"), size=5)+
geom_point(aes(y=max, shape="max"), size=5)+
scale_x_continuous(breaks=c(1:13), labels=c("Insincere","Joking","Suggesting","Irony","Neutral","Serious","Commanding","Praising","Sincere","Friendly","Polite","Hostile", "Rude"))+
xlab("")+ylab("")+theme_bw()+
theme(axis.text.x=element_text(size=25,angle=45, vjust=0.5, color="black"))+
theme(legend.text = element_text(size = 20))+
theme(legend.title = element_text(size = 20))+
labs(shape = "f0:", fill = "SpRate:")+
scale_shape_manual(values=c("min"=15,"max"=16,"mean"=18))+
scale_fill_manual(values= "black")+
theme(axis.text.y = element_text(size=20))
So, as you can see from the plot, there are two plots indeed: A rectanglular with points and a bar-plot, but the y-axis of bar-plot obviously not adapt into the y-axis presented well, so, how to add another y-axis in the right of the whole plot which could adjust for the bar-plot better? (i.e. I want the y-axis of rectangular presented from 0 to 2.5 and bar-plot from 0 to 7)
You could add the second y-axis in ggplot2.
Use this example for one panel plot (http://rpubs.com/kohske/dual_axis_in_ggplot2)
Use my example for multiple panel plot (Dual y axis in ggplot2 for multiple panel figure)