alternative for ggplot2 aes: order function? - r

Does somebody know a alternative method for ordering stacks of a ggplot2 bar graph?
I used to use for example
library(ggplot2)
library(plyr)
a <- cbind(rep("a",5),sample(1:100,5), rep_len(c("1","2","3"),5))
b <- cbind(rep("b",7),sample(1:100,7), rep_len(c("1","2","3"),7))
c <- cbind(rep("c",3),sample(1:100,3), rep_len(c("1","2","3"),3))
d <- cbind(rep("d",10),sample(1:100,10), rep_len(c("1","2","3"),10))
e <- cbind(rep("e",15),sample(1:100,15), rep_len(c("1","2","3"),15))
dat <- rbind(a,b,c,d,e)
colnames(dat) <- c("x","count","example")
dat <- as.data.frame(dat)
dat$x <- as.character(dat$x)
dat$count <- as.numeric(dat$count)
dat$example <- as.character(dat$example)
GP <- ggplot(dat, aes(x= reorder(x, count, sum), y=count, fill = example, order = desc(count)))+
geom_bar(stat="identity", fill= "grey", colour= "black", size = 1)+
coord_flip() +
scale_y_continuous()+
scale_x_discrete('')+
#scale_fill_brewer()+
labs(y="")+
theme_bw()+
theme(axis.text.y=element_text(size=8,face="bold"),
axis.text.x=element_text(size=10,face="bold"),
axis.title.x=element_text(size=16,face="bold"),
axis.title.y=element_text(size=16,face="bold"),
plot.title=element_text(size=16,face="bold"),
strip.text.x = element_text(size=10,face="bold"),
strip.background = element_blank())
print(GP)
to create graphs like
however in version 2.0.0 of ggplot2 order() has been removed. and now the graph will be like:
Does anybody know a alternative?
Tanks

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

Create a Stephan Few bullet chart with a benchmark element

I have the following data:
library(ggplot2)
cbPalette <- c("#000000", "#E69F00")
sentiment <- c(0.2, 0.05)
names <- c("test1", "test2")
df <- data.frame(sentiment, names)
And I use this to create the following plot
p <- ggplot(df, aes(names, sentiment, fill = names))
pp <- p + geom_bar(stat = "identity", colour="black") + coord_flip() + scale_fill_brewer(palette = "Spectral")
This works fine. However I would like to include a benchmark in it. A little like a stephen few bullet chart. So in both charts I want to include a smaller blacker bar that serves a benchmark. Any thoughts on how I can do that?

How to plot a filled.contour plot using ggplot2?

I have some data and I have tried a filled.contour plot which seems nice. However, the legend is hard to control, so I am thinking to use ggplo2. But I have no clue how to plot a filled.contour using ggplot2.
The data contains 840 rows (which stand for the dates), and 12 columns (which stand for 12 time scales). Here is an example
set.seed(66)
Mydata <- sample(x=(-3:3),size = 840*12,replace = T)
Mydata <- matrix(data=Mydata,nrow=840,ncol=12)
Dates <- seq(from=1948+1/24, to= 2018,by=1/12)
data.breaks <- c(-3.5,-2.5,-1.5,0,1.5,2.5,3.5)
filled.contour(Dates,seq(1:12),Mydata,col=cols(11),xlab="",ylab="time-scale",levels=data.breaks)
As we can see, the legend intervals are not what I want. I want to show -3.5,-2.5,-1.5,0,1.5,2.5,3.5on the legend and I believe it is much easier to do this with ggplot2. Thanks for any help.
A ggplot2 alternative to filled.contour is stat_contour.
library(ggplot2)
library(reshape2)
set.seed(66)
Mydata <- sample(x=(-3:3),size = 840*12,replace = T)
Mydata <- matrix(data=Mydata,nrow=840,ncol=12)
Dates <- seq(from=1948+1/24, to= 2018,by=1/12)
data.breaks <- c(-3.5,-2.5,-1.5,0,1.5,2.5,3.5)
rownames(Mydata) <- Dates
d <- melt(Mydata)
colfunc = colorRampPalette(c("brown", "red", "yellow", "white"))
ggplot(d, aes(Var1, Var2, z=value, fill = value)) +
stat_contour(geom="polygon", aes(fill=..level..)) +
scale_fill_gradientn(colours = colfunc(7), breaks=data.breaks, limits=c(-4,4),
values=scales::rescale(data.breaks))+
theme_bw() +
scale_x_continuous(name="", breaks=seq(1950,2010,20), expand=c(0,0)) +
scale_y_continuous(name="time-scale", expand=c(0,0))+
guides(fill = guide_colorbar(barwidth = 2, barheight = 15))

Multiplot using ggplot2

I am using ggplot2 for a multiplot. Althoug after a lot of tweaking, I still face
problems as:
Some free space gets plotted on each side (left/right) of each plot. I have marked this on the right side of each plot.
Plots are not aligned by the left side. This problem is clearly observed in the bottom plot
Y axis label is much far away from the plots. Can I reduce this separation?
Multiplot is:
I used the following R code for the same:
p1 <- ggplot(data = dplots[[1]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.text.x=element_blank(),axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+labs(title="room1")
p2 <- ggplot(data = dplots[[2]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.text.x=element_blank(),axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+ labs(title="room2")
p3 <- ggplot(data = dplots[[6]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.text.x=element_blank(),axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+ labs(title="room3")
p4 <- ggplot(data = dplots[[4]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.text.x=element_blank(),axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+ labs(title="room4")
p5 <- ggplot(data = dplots[[5]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.text.x=element_blank(),axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+ labs(title="room5")
p6 <- ggplot(data = dplots[[3]],aes(timestamp,power/1000))+ geom_line()+
ylab("")+theme(axis.title.x=element_blank(),axis.ticks.x=element_blank(),plot.margin = unit(c(-0.3,1,-0.3,1), "cm"))+ labs(title="Chiller") +
scale_x_datetime(labels= date_format("%d-%m-%y",tz ="UTC"),breaks = pretty_breaks(8))
grid.arrange(p1,p2,p3,p4,p5,p6,nrow=6,ncol=1,heights=c(0.15,0.15,0.15,0.15,0.15,0.15),left="Power (KW)")
The dataset (dplots) is stored at the link.
Probably the easiest solution is to combine the dataframes in the list in one dataset. With rbindlist from the data.table package you can also include id's for each dataframe:
library(data.table)
# bind the dataframes together into one datatable (which is an enhanced dataframe)
DT <- rbindlist(dplots, idcol = "id")
# give names to the id's
DT$id <- factor(DT$id, labels = c("room 1","room 2","room 3", "room 4","room 5","Chiller"))
library(ggplot2)
ggplot(DT, aes(x = timestamp, y = power)) +
geom_line() +
scale_x_datetime(expand = c(0,0)) +
facet_grid(id ~ ., scales="free_y") +
theme_bw()
this results in the following plot:
With your existing code, use cowplot package:
library(cowplot)
plot_grid(p1,p2,p3,p4,p5,p6,ncol=1,align = "v")

How to stack functions?

I have the following code:
library("ggplot2")
base <- ggplot(data.frame(x = c(-5, 5)), aes(x))
f_sin <- stat_function(fun=sin, colour="red", geom="area", position = 'stack', mapping=aes(fill = "red"))
f_cos <- stat_function(fun=cos, colour="green", geom="area", position = 'stack', mapping=aes(fill = "green"))
print(base + f_sin + f_cos)
Which is producing this graph:
Why aren't the areas of the two functions stacked?
In general, you want to do your calculations outside of ggplot. Is this what you wanted?
library(reshape)
df <- data.frame(x=seq(-5,5,0.01))
df$sin <- sin(df$x)
df$cos <- cos(df$x)
df <- melt(df,id="x")
ggplot(df, aes(x=x,y=value,fill=variable)) + geom_area(position="stack")
The red area is sin(x), the green area is 'stacked' (sin+cos).

Resources