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:
Related
So my legend here is village which has (Chirodzo, God, Ruaca). How to remove the legend and display it inside the bars; for instance inside the bar for chirodzo, I want chirodzo written inside?
ggplot(data = interviews_plotting, aes(x = respondent_wall_type, fill = village)) +
geom_bar(position = "fill")
Source is here https://mq-software-carpentry.github.io/r-ggplot-extension/02-categorical-data/index.html
ggplot(data = interviews_plotting, aes(x = respondent_wall_type, fill = village)) +
geom_bar(position = "fill")
To label your bars with the fill category and getting rid of the legend you could use geom_text like so:
Using mtcars as example data:
library(ggplot2)
ggplot(data = mtcars, aes(x = am, fill = factor(cyl))) +
geom_bar(position = "fill") +
geom_text(aes(label = cyl), stat = "count", position = position_fill(vjust = 0.5)) +
guides(fill = "none")
From your comments, it sounds like you are looking for something like this:
library(ggplot2)
ggplot(interviews_plotting, aes(x = respondent_wall_type, fill = village)) +
geom_bar(position = position_dodge()) +
geom_text(stat = 'count',
aes(y = stat(count)/2, label = village, group = village),
position = position_dodge(width = 1), angle = 90) +
guides(fill = guide_none())
Or, if you want to get a bit more sophisticated with your label placement and theme choices:
library(ggplot2)
ggplot(interviews_plotting, aes(x = respondent_wall_type, fill = village)) +
geom_bar(position = position_dodge(width = 0.9), width = 0.8) +
geom_text(stat = 'count', size = 6,
aes(y = ifelse(stat(count) > 2, stat(count)/2, stat(count)),
label = village, group = village,
hjust = ifelse(stat(count) > 2, 0.5, -0.2)),
position = position_dodge(width = 0.9), angle = 90) +
labs(x = 'Wall type', y = 'Count') +
theme_minimal(base_size = 16) +
scale_fill_brewer(palette = 'Set2', guide = 'none')
Data used
interviews_plotting <- read.csv(paste0("https://raw.githubusercontent.com/",
"humburg/r-ggplot-project/master/",
"data_output/interviews_plotting.csv"))
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))
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)
I am trying to overlay a bar chart with a line graph on a single plot with ggplot in R. My line graph works fine but the data are much larger than the data for the bar chart component.
How could I use an additional scale for this bar chart or do something that will get this to look nice all in one graph.
Here is my plot code thus far:
chart <- data.frame("QuantileName" = 1:5, "AvgLoss" = c(100, 500, 1000, 2500, 3000), "AvgFactor" = c(1.0, 1.1, 1.3, 1.4, 1.5))
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5), breaks = seq(1, 5)) +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_bar(aes(y = AvgFactor, colour = "AvgFactor" ), stat = "identity") +
geom_text(aes(y = AvgLoss, label = round(AvgLoss)), position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"), values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5))
Plot
Thank you for any help!
Essentialy, multiply your AvgFactor variable by a number
+ geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ), stat = "identity")
and set
+ scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
so your plot code would look like
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5),
breaks = seq(1, 5)) +
geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ),
stat = "identity") +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_text(aes(y = AvgLoss,
label = round(AvgLoss)),
position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"),
values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5)) +
scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
However, I think it is probably more elegant to avoid secondary axes whenever possible.
It may be useful to know that geom_col(...) is shorthand for geom_bar(..., stat = 'identity')
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)