ggplot geom_col legend not showing - r

I am trying to show a legend to accompany a plot created using ggplot and geom_col - my legend isn't showing up. I originally plotted these data using geom_bar (with a visible legend but some other problems), but after more research it seems more appropriate to use geom_col.
I know this topic has a ton of google-able questions and answers, but after many searches and code variations I still have no success.
How can I make my legend visible?
My reproducible code is below.
site <- c(0.700, 0.854)
site <- lapply(site, function(x) round((x*100),1))
site <- unlist(site, use.names=FALSE)
state <- c(0.726, 0.808)
state <- lapply(state, function(x) round((x*100),1))
state <- unlist(state, use.names=FALSE)
measure <- c("Individual", "Coalition")
measure <- unlist(measure, use.names=FALSE)
df1 <- data.frame(site,state,measure)
df2 <- melt(df1, id.vars='measure')
df2$variable <- factor(df2$variable,
levels = c('state','site'),ordered = TRUE)
fillcolors <- c("#7189A6", "#817BB0", "#7189A6", "#817BB0")
myplot <-
ggplot(df2, aes(measure, value, group = variable)) +
geom_col(width=.75, position=position_dodge(width=0.80), fill=fillcolors) +
labs(title = paste0("Knowledge & Skills Gained", paste0(rep("", 0), collapse = " ")),
x = "", y = "", fill="") +
scale_y_continuous(limits=c(0,100), labels = function(x){ paste0(x, "%") }) +
coord_flip() +
geom_text(aes(label=(paste0(value,"%"))), size=3,
colour = "#57585a",
position=position_dodge(width=0.75), vjust=.3, hjust=-.1) +
theme(legend.position="right", title = element_text(colour = "#57585a"),
legend.text = element_text(colour="#57585a", size = 9))
myplot
This results in the following plot: myplot
Thank you in advance!

The main issue is that you should use fill=, not group=:
ggplot(df2, aes(measure, value, fill = variable)) +
geom_col(width=.75, position=position_dodge(width=0.80)) +
labs(title = paste0("Knowledge & Skills Gained", paste0(rep("", 0), collapse = " ")),
x = "", y = "", fill="") +
scale_y_continuous(limits=c(0,100), labels = function(x){ paste0(x, "%") }) +
coord_flip() +
geom_text(aes(label=(paste0(value,"%"))), size=3,
colour = "#57585a",
position=position_dodge(width=0.75), vjust=.3, hjust=-.1) +
scale_fill_manual(values = c("#817BB0", "#7189A6")) +
guides(fill = guide_legend(reverse=T))
(There are a lot of other ways in which your code could be cleaned up; I focused only on getting the legend to appear.)

Related

Circular tree with heatmap

This question is quite trivial but I cannot be handled nicely with.
I'm trying to plot a circular tree with a side heatmap.
I'm using ggtree but any approach ggplo2 based is welcome.
The problems that I'm not understanding well the gheatmap function.
I want:
1- names AFTER the heatmap
2- 2 text columns after heatmap (for while may have the same value, but I need to know how to add it )
3- heatmap columns name nicely handled, should we remove the columns name and use different colors scales for each? wherever the solution falls might better than the way it is now
library(tidyverse)
library(ggtree)
library(treeio)
library(tidytree)
beast_file <- system.file("examples/MCC_FluA_H3.tree", package="ggtree")
beast_tree <- read.beast(beast_file)
genotype_file <- system.file("examples/Genotype.txt", package="ggtree")
genotype <- read.table(genotype_file, sep="\t", stringsAsFactor=F)
colnames(genotype) <- sub("\\.$", "", colnames(genotype))
p <- ggtree(beast_tree, mrsd="2013-01-01",layout = "fan", open.angle = -270) +
geom_treescale(x=2008, y=1, offset=2) +
geom_tiplab(size=2)
gheatmap(p, genotype, offset=5, width=0.5, font.size=3,
colnames_angle=-45, hjust=0) +
scale_fill_manual(breaks=c("HuH3N2", "pdm", "trig"),
values=c("steelblue", "firebrick", "darkgreen"), name="genotype")
Thanks in advance
UPDATE:
I found a better way to plot the name of heatmap columns.
Also, I found that the simplification of the data was useful to
clean up a little the tip labels.
Now, I just need to add two text columns after heatmap.
p <- ggtree(beast_tree)
gheatmap(
p, genotype, colnames=TRUE,
colnames_angle=90,
colnames_offset_y = 5,
colnames_position = "top",
) +
scale_fill_manual(breaks=c("HuH3N2", "pdm", "trig"),
values=c("steelblue", "firebrick", "darkgreen"), name="genotype")
UPDATE 2:
A very bad improvement
I just used ggplot to create the label and merge with patchwork
library(patchwork)
p$data %>%
ggplot(aes(1, y= y, label = label )) +
geom_text(size=2) +
xlim(NA, 1) +
theme_classic() +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
axis.title.y=element_blank(),
axis.text.y=element_blank(),
axis.ticks.y=element_blank()) -> adText
pp + adText
The answer according #xiangpin at GitHub.
Big offset value to geom_tiplabel:
p <- ggtree(beast_tree)
p1 <- gheatmap(
p, genotype, colnames=TRUE,
colnames_angle=-45,
colnames_offset_y = 5,
colnames_position = "bottom",
width=0.3,
hjust=0, font.size=2) +
scale_fill_manual(breaks=c("HuH3N2", "pdm", "trig"),
values=c("steelblue", "firebrick", "darkgreen"), name="genotype") +
geom_tiplab(align = TRUE, linesize=0, offset = 7, size=2) +
xlim_tree(xlim=c(0, 36)) +
scale_y_continuous(limits = c(-1, NA))
p1
Using ggtreeExtra:
library(ggtreeExtra)
library(ggtree)
library(treeio)
library(ggplot2)
beast_file <- system.file("examples/MCC_FluA_H3.tree", package="ggtree")
genotype_file <- system.file("examples/Genotype.txt", package="ggtree")
tree <- read.beast(beast_file)
genotype <- read.table(genotype_file, sep="\t")
colnames(genotype) <- sub("\\.$", "", colnames(genotype))
genotype$ID <- row.names(genotype)
dat <- reshape2::melt(genotype, id.vars="ID", variable.name = "type", value.name="genotype", factorsAsStrings=FALSE)
dat$genotype <- unlist(lapply(as.vector(dat$genotype),function(x)ifelse(nchar(x)==0,NA,x)))
p <- ggtree(tree) + geom_treescale()
p2 <- p + geom_fruit(data=dat,
geom=geom_tile,
mapping=aes(y=ID, x=type, fill=genotype),
color="white") +
scale_fill_manual(values=c("steelblue", "firebrick", "darkgreen"),
na.translate=FALSE) +
geom_axis_text(angle=-45, hjust=0, size=1.5) +
geom_tiplab(align = TRUE, linesize=0, offset = 6, size=2) +
xlim_tree(xlim=c(0, 36)) +
scale_y_continuous(limits = c(-1, NA))
p2

How to hide (or remove) dots in the boxplot graph?

I have a question about how to hide(or remove) dots in the boxplot graph.
This is code what I implemented.
install.packages("randomForestSRC")
install.packages("ggRandomForests")
library(randomForestSRC)
library(ggRandomForests)
data(pbc, package="randomForestSRC")
pbc.na <- na.omit(pbc)
set.seed(123)
rsf <- rfsrc(Surv(days,status)~., data=pbc.na, ntree=500, importance=T)
gg_v <- gg_variable(rsf, time = c(2000, 4000),
time.labels = c("2000 days", "4000 days"))
gg_v$stage <- as.factor(gg_v$stage)
plot(gg_v, xvar="stage", panel=T, points=F)+
ggplot2::theme_bw() +
ggplot2::geom_boxplot(outlier.shape=NA)+
ggplot2::labs(y="Survival (%)")+
ggplot2::coord_cartesian(ylim=c(-.01, 1.02))
So I would like to hide(or remove) all of the event's dots (both of False and True).
However, I have no information about what I want.
Please let me know how to do it.
Thanks always.
I am not familiar how ggRandomForests work. But using the data frame gg_v, we can directly do the plotting in ggplot2.
ggplot(gg_v, aes(stage, yhat, group = stage)) +
geom_boxplot(outlier.shape = NA) +
facet_wrap(~time, nrow = 2, strip.position = "right") +
ylab("Survival (%)") +
theme_bw()
You can also use the function "geom_boxplot2" from github ("Ipaper")
# devtools::install_github('kongdd/Ipaper')
library(Ipaper)
library(ggplot2)
ggplot(gg_v, aes(stage, yhat, group = stage)) +
geom_boxplot2(width = 0.8, width.errorbar = 0.5)+
facet_wrap(~time, nrow = 2, strip.position = "right") +
ylab("Survival (%)") +
theme_bw()

ggplot2 - change line color depending on variable name

I would like to plot the values of several tables. Each of these tables have a different/unknown number of variables/columns.
I am using the following code in order to plot the data:
library(ggplot2)
library(reshape2)
#data <- read.table("jony.csv", header = TRUE, sep = ";", fill = TRUE)
data <- read.table(text="MONTH;GFDL.ESM2M_HBV_IWW_WFDisi;GFDL.ESM2M_SWIM;GFDL.ESM2M_WaterGAP3;GFDL.ESM2M_HYPE;GFDL.ESM2M_VIC;month_mean;q70
1;853.455161290323;550.116774193548;746.965913978495;469.31688172043;546.64752688172;633.300451612903;452.931661075269
2;1037.55011792453;632.34445754717;805.189285714286;567.411202830189;763.929245283019;761.284861859839;452.931661075269
3;782.714301075269;447.378494623656;561.674193548387;422.475483870968;591.257634408602;561.100021505376;452.931661075269
", header = TRUE, sep = ";", fill = TRUE)
jony <- melt(data, id.vars="MONTH")
p <- ggplot(jony, aes(MONTH,value, col=variable))
p + geom_line(size = 0.1) +
geom_hline(aes(yintercept = 0), linetype="dotted") +
ylab("Runoff [m3/s]") +
xlab("Month") +
theme_bw() +
theme(legend.key = element_blank())+
scale_color_discrete(name='Models GCM_HM') +
ggtitle("Jony")
So with this code, ggplot2 assign automatically a color for each of my variables. My problem is that I would like to assign manually a color just for the last two variables "month_mean" and "q70". I have tried different ways, but it seems that then I need to assign manually a color for each of my variables (which is not making sens in my case because I have way too many data to threat and the number of variables is not constant). Does anyone knows a workaround in order to assign manually a color for those two variables?
Maybe use some sort of a helper function, e.g.
p <- ggplot(jony, aes(MONTH,value, col=variable)) +
geom_line(size = 0.1) +
geom_hline(aes(yintercept = 0), linetype="dotted") +
ylab("Runoff [m3/s]") +
xlab("Month") +
theme_bw() +
theme(legend.key = element_blank())+
scale_color_discrete(name='Models GCM_HM') +
ggtitle("Jony")
f <- function(x,cols,pal=rainbow) {
stopifnot(names(cols) %in% x)
pal <- pal(length(x)-length(cols))
names(pal) <- setdiff(x, names(cols))
pal <- c(pal, cols)
return(pal)
}
p + scale_color_manual(
values = f(levels(jony$variable), c("month_mean"="black", "q70"="cyan"), grey.colors )
)
Probably room for improvement, but...

Ordering ggplot legend by the final value in a data frame

I would like to re-order the elements in a legend, as they appear top to bottom in an R ggplot. That is: I'd like the order dictated by comparing the Y value at the right most point X axis point. In the following data, I'd like the legend to read from the top: bush, foo, baz, bar.
Update: following #alexwhan comments, I have added the data to the script.
Update 2: this is now exactly what I was hoping for, thanks to #thomas-kern on #R (bosie) irc.freenode. The trick was to add both, i.e.
scale_linetype_discrete(breaks = ord$Variant) + scale_shape_discrete(breaks = ord$Variant)
Here's my R:
library(plyr)
library(ggplot2)
require(grid)
args <- commandArgs(trailingOnly = TRUE)
lines <- "
X,Variant,Y
1,foo,123
1,bar,134
1,baz,135
1,bush,136
2,foo,221
2,bar,104
2,baz,155
2,bush,336
"
con <- textConnection(lines)
DF <- read.csv(con, header=TRUE)
close(con)
cdata <- ddply(DF, .(Variant,X), summarise, N = length(Y), mean=round(mean(Y),2), sd=round(sd(Y),2), se=round(sd(Y)/sqrt(length(Y)),2))
ord <- cdata[cdata$X == max(cdata$X),]
ord <- ord[order(ord$Variant, decreasing=T),]
pdf("out.pdf")
none <- element_blank()
bp <- ggplot(cdata, aes(x=X, y=mean, group=Variant)) + xlab("X label") + geom_line(aes(linetype=Variant)) + geom_point(aes(shape=Variant)) + ylab("Y Value") + labs(title = "mytitle") + scale_linetype_discrete(breaks = ord$Variant) + scale_shape_discrete(breaks = ord$Variant)
print(bp + theme(legend.justification=c(1,0), legend.position=c(1,0), legend.key.width=unit(3,"line"), legend.title=element_blank(), text = element_text(size=18)) + theme(panel.background = element_rect(fill='white', colour='black')) + theme(panel.grid.major = none, panel.grid.minor = none))
dev.off()
This generates exactly what I'm after:
It really helps if you provide the data your plot is made with. Here's an example of how to approach with some data I made up:
dat <- data.frame(x = c(1,2), y = rnorm(8), group = rep(c("bar", "baz", "bush", "foo"), each = 2))
ord <- dat[dat$x == max(dat$x),]
ord <- ord[order(ord$y, decreasing=T),]
ggplot(dat, aes(x, y)) + geom_point(aes(shape = group)) + geom_line(aes(group = group)) +
scale_shape_discrete(breaks = ord$group)

Different font faces and sizes within label text entries in ggplot2

I am building charts that have two lines in the axis text. The first line contains the group name, the second line contains that group population. I build my axis labels as a single character string with the format "LINE1 \n LINE2". Is it possible to assign different font faces and sizes to LINE1 and LINE2, even though they are contained within a single character string? I would like LINE1 to be large and bolded, and LINE2 to be small and unbolded.
Here's some sample code:
Treatment <- rep(c('T','C'),each=2)
Gender <- rep(c('Male','Female'),2)
Response <- sample(1:100,4)
test_df <- data.frame(Treatment, Gender, Response)
xbreaks <- levels(test_df$Gender)
xlabels <- paste(xbreaks,'\n',c('POP1','POP2'))
hist <- ggplot(test_df, aes(x=Gender, y=Response, fill=Treatment, stat="identity"))
hist + geom_bar(position = "dodge") + scale_y_continuous(limits = c(0,
100), name = "") + scale_x_discrete(labels=xlabels, breaks = xbreaks) +
opts(
axis.text.x = theme_text(face='bold',size=12)
)
I tried this, but the result was one large, bolded entry, and one small, unbolded entry:
hist + geom_bar(position = "dodge") + scale_y_continuous(limits = c(0,
100), name = "") + scale_x_discrete(labels=xlabels, breaks = xbreaks) +
opts(
axis.text.x = theme_text(face=c('bold','plain'),size=c('15','10'))
)
Another possible solution is to create separate chart elements, but I don't think that ggplot2 has a 'sub-axis label' element available...
Any help would be very much appreciated.
Cheers,
Aaron
I also think that I could not to make the graph by only using ggplot2 features.
I would use grid.text and grid.gedit.
require(ggplot2)
Treatment <- rep(c('T','C'), each=2)
Gender <- rep(c('Male','Female'), 2)
Response <- sample(1:100, 4)
test_df <- data.frame(Treatment, Gender, Response)
xbreaks <- levels(test_df$Gender)
xlabels <- paste(xbreaks,'\n',c('',''))
hist <- ggplot(test_df, aes(x=Gender, y=Response, fill=Treatment,
stat="identity"))
hist + geom_bar(position = "dodge") +
scale_y_continuous(limits = c(0, 100), name = "") +
scale_x_discrete(labels=xlabels, breaks = xbreaks) +
opts(axis.text.x = theme_text(face='bold', size=12))
grid.text(label="POP1", x = 0.29, y = 0.06)
grid.text(label="POP2", x = 0.645, y = 0.06)
grid.gedit("GRID.text", gp=gpar(fontsize=8))
Please try to tune a code upon according to your environment (e.g. the position of sub-axis labels and the fontsize).
I found another simple solution below:
require(ggplot2)
Treatment <- rep(c('T','C'),each=2)
Gender <- rep(c('Male','Female'),2)
Response <- sample(1:100,4)
test_df <- data.frame(Treatment, Gender, Response)
xbreaks <- levels(test_df$Gender)
xlabels[1] <- expression(atop(bold(Female), scriptstyle("POP1")))
xlabels[2] <- expression(atop(bold(Male), scriptstyle("POP2")))
hist <- ggplot(test_df, aes(x=Gender, y=Response, fill=Treatment,
stat="identity"))
hist +
geom_bar(position = "dodge") +
scale_y_continuous(limits = c(0, 100), name = "") +
scale_x_discrete(label = xlabels, breaks = xbreaks) +
opts(
axis.text.x = theme_text(size = 12)
)
All,
Using Triad's cheat this is the closest I was able to get to solution on this one. Let me know if you have any questions:
library(ggplot2)
spacing <- 0 #We can adjust how much blank space we have beneath the chart here
labels1= paste('Group',c('A','B','C','D'))
labels2 = rep(paste(rep('\n',spacing),collapse=''),length(labels1))
labels <- paste(labels1,labels2)
qplot(1:4,1:4, geom="blank") +
scale_x_continuous(breaks=1:length(labels), labels=labels) + xlab("")+
opts(plot.margin = unit(c(1, 1, 3, 0.5), "lines"),
axis.text.x = theme_text(face='bold', size=14))
xseq <- seq(0.15,0.9,length.out=length(labels)) #Assume for now that 0.15 and 0.9 are constant plot boundaries
sample_df <- data.frame(group=rep(labels1,each=2),subgroup=rep(c('a','b'),4),pop=sample(1:10,8))
popLabs <- by(sample_df,sample_df$group,function(subData){
paste(paste(subData$subgroup,' [n = ', subData$pop,']',sep=''),collapse='\n')
})
gridText <- paste("grid.text(label='\n",popLabs,"',x=",xseq,',y=0.1)',sep='')
sapply(gridText, function(x){ #Evaluate parsed character string for each element of gridText
eval(parse(text=x))
})
grid.gedit("GRID.text", gp=gpar(fontsize=12))
Cheers,
Aaron

Resources