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 add legend on ggplot2.
When I use the following codes, I get the following plot.
ggplot() +
geom_bar(data = profitCountries, aes(y = (revenue), x = residence), stat="identity",
fill="darkgreen", color = "black") +
geom_bar(data = profitCountries, aes(y = -(total_spend), x = residence), stat="identity",
fill="red", color = "black") +
geom_line(data = profitCountries, aes(y = total_profit, x = residence, group = 1), size = 1.5,
color = "blue" ) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') + ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') + theme_grey()
As suggested in other posts, I added color inside aes(). When I try to do that using the following code, I get the following plot.
ggplot() +
geom_bar(data = profitCountries, aes(y = (revenue), x = residence, fill="darkgreen"), stat="identity",
color = "black") +
geom_bar(data = profitCountries, aes(y = -(total_spend), x = residence, fill="red"), stat="identity",
color = "black") +
geom_line(data = profitCountries, aes(y = total_profit, x = residence, group = 1, color = "blue"),
size = 2 ) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') + ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') + theme_grey()
In the second plot, the colors change and two legends are created. Is there anyway to solve this?
You are currently mapping the character vector green to a manual scale whose colors are automatically determined.
You probably want
ggplot(profitCountries, aes(residence)) +
geom_bar(aes(y = (revenue), fill="Revenue"), stat="identity",
color = "black") +
geom_bar(aes(y = -(total_spend), fill="Campaign Spending"), stat="identity",
color = "black") +
geom_line(aes(y = total_profit, group = 1, color = "Net"), size = 2) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') +
ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') +
theme_grey() +
scale_fill_manual(values = c("Revenue" = "darkgreen", "Campaign Spending" = "red")) +
scale_color_manual(values = c("Net" = "blue"))
I wanted to comment on the following doubt.
Using this code:
Plot<-data.frame(Age=c(0,0,0,0,0),Density=c(0,0,0,0,0),Sensitivity=c(0,0,0,0,0),inf=c(0,0,0,0,0),sup=c(0,0,0,0,0),tde=c(0,0,0,0,0))
Plot[1,]<-c(1,1,0.857,0.793,0.904,0.00209834)
Plot[2,]<-c(1,2,0.771 ,0.74,0.799,0.00348286)
Plot[3,]<-c(1,3,0.763 ,0.717,0.804,0.00577784)
Plot[4,]<-c(1,4,0.724 ,0.653,0.785,0.00504161)
Plot[5,]<-c(2,1,0.906,0.866,0.934,0.00365742)
Plot[6,]<-c(2,2,0.785 ,0.754,0.813,0.00440399)
Plot[7,]<-c(2,3,0.660,0.593,0.722,0.00542849)
Plot[8,]<-c(2,4,0.544,0.425,0.658,0.00433052)
names(Plot)<-c("Age","Mammographyc density","Sensitivity","inf","sup","tde")
Plot$Age<-c("50-59","50-59","50-59","50-59","60-69","60-69","60-69","60-69")
Plot$Density<-c("Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense","Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense")
levels(Plot$Age)<-c("50-59","60-69")
levels(Plot$Density)<-c("Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense")
pd <- position_dodge(0.2) #
Plot$Density <- reorder(Plot$Density, 1-Plot$Sensitivity)
ggplot(Plot, aes(x = Density, y = 100*Sensitivity, colour=Age)) +
geom_errorbar(aes(ymin = 100*inf, ymax = 100*sup), width = .1, position = pd) +
geom_line(position = pd, aes(group = Age), linetype = c("dashed")) +
geom_point(position = pd, size = 4)+
scale_y_continuous(expand = c(0, 0),name = 'Sensitivity (%)',sec.axis = sec_axis(~./5, name = 'Breast cancer detection rate (per 1000 mammograms)', breaks = c(0,5,10,15,20),
labels = c('0‰',"5‰", '10‰', '15‰', '20‰')), limits = c(0,100)) +
geom_line(position = pd, aes(x = Density, y = tde * 5000, colour = Age, group = Age), linetype = c("dashed"), data = Plot) +
geom_point(shape=18,aes(x = Density, y = tde * 5000, colour = Age, group = Age), position = pd, size = 4) +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
theme(legend.position="bottom") + guides(colour = guide_legend(), size = guide_legend(),
shape = guide_legend())
I have made the following graph,
in which the axis on the left is the scale of the circles and the axis on the right is the scale of the diamonds. The fact is that I would like to have a legend approximately like this:
But it is impossible for me, I have tried suggestions of other threads like scale_shape and different commands in guides but I have not got success. I just want to make clear the difference in what shape and color represent.
Would someone know how to help me?
Best regards,
What you should do is a panel plot to avoid the confusion of double axes:
library(dplyr)
library(tidyr)
Plot %>%
gather(measure, Result, Sensitivity, tde) %>%
ggplot(aes(x = Density, y = Result, colour=Age)) +
geom_errorbar(aes(ymin = inf, ymax = sup), width = .1, position = pd,
data = . %>% filter(measure == "Sensitivity")) +
geom_line(aes(group = Age), position = pd, linetype = "dashed") +
geom_point(position = pd, size = 4)+
# scale_y_continuous(expand = c(0, 0), limits = c(0, 1)) +
scale_y_continuous(labels = scales::percent) +
facet_wrap(~measure, ncol = 1, scales = "free_y") +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
theme(legend.position="bottom")
But to do what you asked, you problem is that you have only 1 non-positional aesthetic mapped so you cannot get more than one legend. To force a second legend, you need to add a second mapping. It can be a dummy mapping that has no effect, as below we map alpha but then manually scale both levels to 100%. This solution is not advisable because, as you have done in your example of a desired legend, it is easy to mix up the mappings and have your viz tell a lie by mislabeling which points are sensitivity and which are detection rate.
ggplot(Plot, aes(x = Density, y = 100*Sensitivity, colour=Age, alpha = Age)) +
geom_errorbar(aes(ymin = 100*inf, ymax = 100*sup), width = .1, position = pd) +
geom_line(position = pd, aes(group = Age), linetype = c("dashed")) +
geom_point(position = pd, size = 4)+
scale_y_continuous(expand = c(0, 0),name = 'Sensitivity (%)',sec.axis = sec_axis(~./5, name = 'Breast cancer detection rate (per 1000 mammograms)', breaks = c(0,5,10,15,20),
labels = c('0‰',"5‰", '10‰', '15‰', '20‰')), limits = c(0,100)) +
geom_line(position = pd, aes(x = Density, y = tde * 5000, colour = Age, group = Age), linetype = c("dashed"), data = Plot) +
geom_point(shape=18,aes(x = Density, y = tde * 5000, colour = Age, group = Age), position = pd, size = 4) +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
scale_alpha_manual(values = c(1, 1)) +
guides(alpha = guide_legend("Sensitivity"),
color = guide_legend("Detection Rate", override.aes = list(shape = 18))) +
theme(legend.position="bottom")
This is my data:
> sum.ex
Timepoint mean n sd Time Group
A1 A1-All 1.985249 26 1.000180 A1 All
A1-pT2D A1-pT2D 1.913109 13 1.012633 A1 pT2D
A1-Control A1-Control 2.934105 13 2.472951 A1 Control
B1 B1-All 2.555601 25 1.939970 B1 All
B1-pT2D B1-pT2D 2.057389 13 1.023416 B1 pT2D
B1-Control B1-Control 2.145555 12 1.089522 B1 Control
This is my code:
png('ex')
ggplot(sum.ex, aes(x = Timepoint, y = mean)) +
geom_bar(width = 0.5, position = position_dodge(width = 200), stat="identity", aes(fill = Group)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), size = 1, shape = 1, width = 0.2) +
scale_fill_manual(values = c("#333333", "#FF0000", "#0000FF")) +
xlab(NULL) +
ggtitle("PLIN1") + theme_bw() + theme(panel.grid.major = element_blank())
dev.off()
This is the output:
However, I want to have Black+Red+Blue really close, then a space and then Black+Red+Blue really close again.
Thank you!
I think this is easiest to achieve if you use x = Time and fill = Group. Something like:
dodge <- position_dodge(width = 0.5)
ggplot(df, aes(x = Time, y = mean, fill = Group)) +
geom_bar(width = 0.5, stat="identity", position = dodge) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd),
position = dodge, size = 1, shape = 1, width = 0.2) +
scale_fill_manual(values = c("#333333", "#FF0000", "#0000FF")) +
theme_bw() +
theme(panel.grid.major = element_blank())
Plot against Time only, then position_dodge has meaning for the bars (there are 3 observations per group). Use position_dodge with width close to the bar width. Add group=Group to make the errorbars behave like the bars (you need it since they don't have colour aesthetic to distinguish them). Use the same position_dodge width as before to align them properly.
ggplot(sum.ex, aes(x = Time, y = mean)) +
geom_bar(width = 0.5, position = position_dodge(width = 0.5), stat = "identity", aes(fill = Group)) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd, group=Group), position=position_dodge(width = 0.5), size = 1, shape = 1, width = 0.2) +
scale_fill_manual(values = c("#333333", "#FF0000", "#0000FF")) +
xlab(NULL) +
ggtitle("PLIN1") + theme_bw() + theme(panel.grid.major = element_blank())