Aligning text on bar chart ggplot2 - r

df.test <- data.frame(val=c(0.55,0.42,-0.05),name=letters[1:3],
desc='This is the description of values'
p <- ggplot(df.test, aes(name, val, label = desc)) +
geom_bar(stat = "identity", col = 'black', fill = 'lightgreen') +
labs(title = "Test", x = " ", y = "value", fill = "") +
theme_bw() +
guides(fill = FALSE)
p + geom_text(angle = 90, size = 8, hjust = 1.25, position = position_dodge(width = 0.9))
This generates the following plot:
I want to align the text and force the it to start at the beginning of each chart, so that all of them can be visible (it is ok if it falls outside the small chart). How can I achieve this?

Is this what you're looking for?
p <- ggplot(df.test,aes(name,val,label=desc))+
geom_bar(stat="identity",col='black',fill='lightgreen')+
labs(title = "Test", x = " ", y = "value",fill = "")+
theme_bw()+
guides(fill=FALSE)
p+geom_text(angle=90,size=8,hjust=0,aes(x=name,y=rep(0,nrow(df.test)),label=desc),inherit.aes=F)

Related

Breaking y-axis in ggplot2 with geom_bar

I'm having a hard time dealing with this plot.
The height of values in ANI>96 making it hard to read the red and blue percentage text.
I failed to break the y-axis by looking at answers from other posts in StackOverflow.
Any suggestions?
Thanks.
library(data.table)
library(ggplot2)
dt <- data.table("ANI"= sort(c(seq(79,99),seq(79,99))), "n_pairs" = c(5, 55, 13, 4366, 6692, 59568, 382873, 397996, 1104955, 282915,
759579, 261170, 312989, 48423, 120574, 187685, 353819, 79468, 218039, 66314, 41826, 57668, 112960, 81652, 28613,
64656, 21939, 113656, 170578, 238967, 610234, 231853, 1412303, 5567, 4607268, 5, 14631942, 0, 17054678, 0, 3503846, 0),
"same/diff" = rep(c("yes","no"), 21))
for (i in 1:nrow(dt)) {
if (i%%2==0) {
next
}
total <- dt$n_pairs[i] + dt$n_pairs[i+1]
dt$total[i] <- total
dt$percent[i] <- paste0(round(dt$n_pairs[i]/total *100,2), "%")
dt$total[i+1] <- total
dt$percent[i+1] <- paste0(round(dt$n_pairs[i+1]/total *100,2), "%")
}
ggplot(data=dt, aes(x=ANI, y=n_pairs, fill=`same/diff`)) +
geom_text(aes(label=percent), position=position_dodge(width=0.9), hjust=0.75, vjust=-0.25) +
geom_bar(stat="identity") + scale_x_continuous(breaks = dt$ANI) +
labs(x ="ANI", y = "Number of pairs", fill = "Share one common species taxonomy?") +
theme_classic() + theme(legend.position="bottom")
Here is the list of major changes I made:
I reduced the y axis by zooming into the chart with coord_cartesian (which is called by coord_flip).
coord_flip shouuld also improve the readability of the chart by switching x and y. I don't know if the switch is a desirable output for you.
Also now position_dodge, works as expected: two bars next to each other with the labels on top (on the left in this case).
I set geom_bar before geom_text so that the text is always in front of the bars in the chart.
I set scale_y_continuous to change the labels of the y axis (in the chart the x axis because of the switch) to improve the readability of the zeros.
ggplot(data=dt, aes(x = ANI, y = n_pairs, fill = `same/diff`)) +
geom_bar(stat = "identity", position = position_dodge2(width = 1), width = 0.8) +
geom_text(aes(label = percent), position = position_dodge2(width = 1), hjust = 0, size = 3) +
scale_x_continuous(breaks = dt$ANI) +
scale_y_continuous(labels = scales::comma) +
labs(x ="ANI", y = "Number of pairs", fill = "Share one common species taxonomy?") +
theme_classic() +
theme(legend.position = "bottom") +
coord_flip(ylim = c(0, 2e6))
EDIT
Like this columns and labels are stacked but labels never overlap.
ggplot(data=dt, aes(x = ANI, y = n_pairs, fill = `same/diff`)) +
geom_bar(stat = "identity", width = 0.8) +
geom_text(aes(label = percent,
hjust = ifelse(`same/diff` == "yes", 1, 0)),
position = "stack", size = 3) +
scale_x_continuous(breaks = dt$ANI) +
scale_y_continuous(labels = scales::comma) +
labs(x ="ANI", y = "Number of pairs", fill = "Share one common species taxonomy?") +
theme_classic() +
theme(legend.position = "bottom") +
coord_flip(ylim = c(0, 2e6))
Alternatively, you can avoid labels overlapping with check_overlap = TRUE, but sometimes one of the labels will not be shown.
ggplot(data=dt, aes(x = ANI, y = n_pairs, fill = `same/diff`)) +
geom_bar(stat = "identity", width = 0.8) +
geom_text(aes(label = percent), hjust = 1, position = "stack", size = 3, check_overlap = TRUE) +
scale_x_continuous(breaks = dt$ANI) +
scale_y_continuous(labels = scales::comma) +
labs(x ="ANI", y = "Number of pairs", fill = "Share one common species taxonomy?") +
theme_classic() +
theme(legend.position = "bottom") +
coord_flip(ylim = c(0, 2e6))

How to add name for each column to geom_tile plot

To my geom_tile plot I need columns names, here 6, above the first row and below the subtitle
I tried adding it by
geom_text(x=10, y=10, label="testTEXT") +
but it doesn't show. Perhaps the coordinates are wrong (I tested various value)?
Here the full code:
library(tidyverse)
s1 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s2 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s3 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s4 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s5 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s6 = sample(c("p1","p12","p3","p14","p5","p13"),6)
groupsNo = 6
BLUB = c(s1,s2,s3,s4,s5,s6)
df <- cbind.data.frame(items = BLUB,
x = rep((1:groupsNo),each = length(s1)),
y = rep(1:length(s1), groupsNo),
color = BLUB)
p1 <- ggplot(df,aes(x = x, y = y,fill=factor(color))) +
geom_line(aes(group = items,color=factor(color)), size = 2) +
geom_tile(width = 0.6, height = 0.6, color = 'black') +
theme_void() +
geom_text(aes(label = items), size=5) +
# geom_text(x=100, y=0, label="testTEXT") +
theme(legend.position = "none") +
labs(
y = "", x = "",
title = "Plot for random data",
subtitle = "text",
caption = "text")
print(p1)
The basic problem with your plot is the use of theme_void() which blanks almost all plot labels. You have to override this by specifying the theme for axis text and then blanking the y axis.
You can position the x axis labels at the top by specifying position = "top" in the scale_x_continuous function. You'll also need to explicitly specify the breaks to have labels for all columns. The revised code would be:
p1 <- ggplot(df,aes(x = x, y = y, fill=factor(color))) +
geom_line(aes(group = items,color=factor(color)), size = 2) +
geom_tile(width = 0.6, height = 0.6, color = 'black') +
theme_void() +
theme(axis.text = element_text(size = 12, color = "black",
inherit.blank = FALSE))+
theme(axis.text.y = element_blank()) +
scale_x_continuous(position = "top", breaks = df$x ) +
#
# If x were a character value rather than a numeric one,
# replace scale_x_continuous(..) with
# scale_x_discrete( position = "top") +
#
geom_text(aes(label = items), size=5) +
theme(legend.position = "none") +
labs(
y = "", x = "",
title = "Plot for random data",
subtitle = "text",
caption = "text")
print(p1)
Try this:
library(tidyverse)
s1 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s2 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s3 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s4 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s5 = sample(c("p1","p12","p3","p14","p5","p13"),6)
s6 = sample(c("p1","p12","p3","p14","p5","p13"),6)
groupsNo = 6
BLUB = c(s1,s2,s3,s4,s5,s6)
df <- cbind.data.frame(items = BLUB,
x = rep((1:groupsNo),each = length(s1)),
y = rep(1:length(s1), groupsNo),
color = BLUB)
ggplot(df,aes(x = x, y = y,fill=factor(color))) +
geom_line(aes(group = items,color=factor(color)), size = 2) +
geom_tile(width = 0.6, height = 0.6, color = 'black') +
theme_void() +
geom_text(aes(label = items), size=5) +
annotate(geom="text", x=unique(df$x), y=max(df$y)+0.5, label="testTEXT") +
theme(legend.position = "none") +
labs(
y = "", x = "",
title = "Plot for random data",
subtitle = "text",
caption = "text")

Adding text labels over barplot with ggplotly in R

I have the following dataframe in R
DF_1<-data.frame("ID"=c("A_1", "A_2"), 'Sum'= c(2500,12500), "RR"=
c(95,95), "CC"= c(50,50), "nn"=c(4,4), "DP"= c(12.5,100))
I have created the following barplot with text written in the barplot as follows
p2<-ggplot(data = DF_1, mapping = aes(x = ID, y = DP,
fill=str_wrap(ID,10))) + geom_bar(stat = 'identity', width = .35, position
= "dodge")+ geom_text(aes(label=RR) , position = position_dodge(0.9),vjust
= 2,check_overlap = TRUE)+geom_text(aes(label=CC) , position = postion_dodge(0.9),vjust = 4,check_overlap = TRUE)+ geom_text(aes(label=nn) , position = position_dodge(0.9),vjust = 6,check_overlap = TRUE)+ labs(fill = "LEGEND")+labs(x = "XLabels", y= "DPP")+theme(legend.key.height = unit( 2 ,"cm"))+theme(axis.text.x=element_blank())+ggtitle("DPPCHART")+ theme(plot.title = element_text(hjust = 0.5))
In the plot so generated the three text labels are generated clearly on the barplot. The next step is to make dynamic ticks work
p<-ggplotly(p, dynamicticks=T)
Now the three text labels overlap each other.
Is there a way to retain the text labels separately when using ggplotly.
You can use HTML directly inside the labels like this to remove the overlap:
library(stringr)
library(ggplot2)
library(plotly)
DF_1 <- data.frame("ID"=c("A_1", "A_2"), 'Sum'= c(2500,12500),
"RR"= c(95,95), "CC"= c(50,50), "nn"=c(4,4), "DP"= c(12.5,100))
p <- ggplot(data = DF_1, mapping = aes(x = ID, y = DP,fill=str_wrap(ID,10))) +
geom_bar(stat = 'identity', width = .35, position = "dodge") +
geom_text(aes(label=paste0(RR, "<br>", CC, "<br>", nn)) ,
position = position_dodge(0.9), vjust = 2, check_overlap = TRUE) +
labs(fill = "LEGEND") + labs(x = "XLabels", y= "DPP") +
theme(legend.key.height = unit( 2 ,"cm")) +
theme(axis.text.x=element_blank()) +
ggtitle("DPPCHART") +
theme(plot.title = element_text(hjust = 0.5)) +
scale_y_continuous(limits = c(0,110))
ggplotly(p) # can use with or without dynamicTicks=TRUE
Output is:

Adding text outside the ggplot area

I am trying to make a combo chart using ggplot2. However i want to add a text box sort outside my plot body. I am unable to place it at the desired location
I have used grid pack to create grob and include that in annotation in the ggplot code. Additionally i have also put the same text in geom_text. How do i ensure the text comes say below the legend. Following is my code
m <- ggplot() +
geom_area(data= (ly_vol_ntwk %>%
mutate(Wk_end_d = as.factor(Wk_end_d))%>%
filter(!is.na(value_new))),
aes(x = Wk_end_d, y = value_new ,group = variable,fill=variable))+
geom_bar(data = (fcst_act_vol_ntwk %>%
mutate(Wk_end_d = as.factor(Wk_end_d))%>%
filter(!is.na(value_new))),
aes(x = Wk_end_d, y = value_new, group = variable, fill = variable),
stat = "identity",position = "dodge", width =0.5)+
geom_line(data = (var_vol_ntwk %>%
mutate(Wk_end_d = as.factor(Wk_end_d))%>%
filter(!is.na(value_new))),
aes(x = Wk_end_d, y = value_new,
group = variable, fill= variable), size = 0.8)+
scale_y_continuous(sec.axis = sec_axis(trans = ~./100000,
name = "Variance", breaks = waiver(),
labels=function(x) paste0(x,"%")))+
theme_set(theme_bw())+
theme(axis.text.x = element_text(angle=65, vjust=0.5,face = "plain"),
text = element_text(size=9), legend.position = "bottom", legend.title = element_blank())+
labs(title= "Inbound - Network", x= "Week end date", y = " ")+
scale_fill_manual(values = c("#C5E0B4","#7030A0", "#D9D9D9","#ED7D31","black"))+
geom_text(label = "LW Variance",
aes(x = 19, y = -1960000),
check_overlap = TRUE) #annotation_custom(grob = textGrob("LW Variance"), xmin = 18, xmax = 18, ymin = -1030000, ymax = -1030000)+ coord_cartesian(clip = 'off')
I need to get the text box with a border outside the area of the ggplot. Can you please help me?
You can place text below plot area with labs(caption = "text"), but you can't place captions on top of the plot. However, you could use subtitles labs(subtitle = "text") to produce a similar visual of captions on the top.
To further control the aspect of both options use theme(plot.caption = element_text(...), plot.subtitle = element_text(...)). Type ?element_text in your console to get all the options for text formatting.
For example:
library(ggplot2)
df <- data.frame(x = rnorm(50), y = rnorm(50))
ggplot(df, aes(x, y)) +
geom_point() +
labs(subtitle = "Your text here", caption = "Your text here") +
theme(plot.caption = element_text(colour = "red", hjust = 0, angle = 15),
plot.subtitle = element_text(size = 18, face = "bold", hjust = 0.8))
If you want it below your current legend, you can always add a dummy legend and put your text as its name. An example:
ggplot(mtcars, aes(mpg, wt, color = gear,fill = "a")) +
geom_point() +
scale_fill_discrete(name = "Your custom caption\ngoes here", labels = "") +
theme(legend.key = element_rect(fill = "white")) +
guides(color = guide_legend(order = 1),
fill = guide_legend(order = 2, override.aes = list(linetype = 0, shape=NA))) # setting the order parameter in guide_legend will help place it below your existing legend(s)

ggplot add text to the center of a donut chart in R

I am working on a donut chart using ggplot2, but I need the center of the plot to contain text.
Here's sample data (found from this site: https://www.datanovia.com/en/blog/how-to-create-a-pie-chart-in-r-using-ggplot2/):
library(dplyr)
count.data <- data.frame(
class = c("1st", "2nd", "3rd", "Crew"),
n = c(325, 285, 706, 885),
prop = c(14.8, 12.9, 32.1, 40.2)
)
count.data <- count.data %>%
arrange(desc(class)) %>%
mutate(lab.ypos = cumsum(prop) - 0.5*prop)
count.data
I then modified their code to get this donut chart:
library(ggplot2)
library(dplyr)
mycols <- c("#0073C2FF", "#EFC000FF", "#868686FF", "#CD534CFF")
ggplot(count.data, aes(x = 2, y = prop, fill = class)) +
geom_bar(stat = "identity", color = "white") +
coord_polar(theta = "y", start = 0)+
geom_text(aes(y = lab.ypos, label = paste0("n = ", n, ", \n", prop, "%")), color = "white")+
scale_fill_manual(values = mycols) +
theme_void() +
xlim(.5, 2.5)
The plot looks like this:
It is exactly what I want except I need the center of the donut to have the proportion from a variable. In this case, I want the center to say 40.2% (the prop of crew, in this example).
How do I do this?
Edit
Used annotate as suggested by #aosmith and made it a direct call to crew.
like this?
ggplot(count.data, aes(x = 2, y = prop, fill = class)) +
geom_bar(stat = "identity", color = "white") +
coord_polar(theta = "y", start = 0)+
geom_text(aes(y = lab.ypos, label = paste0("n = ", n, ", \n", prop, "%")), color = "white")+
scale_fill_manual(values = mycols) +
theme_void() +
xlim(.5, 2.5) +
annotate(geom = 'text', x = 0.5, y = 0, label = paste0(count.data$prop[count.data$class == 'Crew'], "%"))

Resources