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))
Related
I have bar charts faceted by stock symbol name:
I would like to be able to add a little "subplot" of an indicator below each plot, like this:
Is this possible with ggplot2? I thought of a secondary axis, but most often there is no linear relation between the main plot axis and the indicator axis (so using sec_axis is not an option).
Thanks!
Since these appear to be categorically different types of plots, I think you'll have better luck creating separate plots and then rendering them together. Here's one solution using cowplot package:
library(ggplot2)
library(cowplot)
#sample data
df <- data.frame(x = 1:100, y = cumsum(rnorm(100)), volume = sample(1:10, 100, replace = TRUE))
p1 <- ggplot(df, aes(x,y)) +
geom_line()
p2 <- ggplot(df, aes(x,volume)) +
geom_bar(stat = "identity")
plot_grid(p1, p2, align = "v", ncol = 1, rel_heights = c(.8, .2))
Created on 2019-01-25 by the reprex package (v0.2.1)
Edit
Continuing to build on this kludgy example to support the concept of faceting. Ignore the ugly graph, it's smooshed due to image size constraints.
library(ggplot2)
library(cowplot)
library(gridExtra)
#sample data
df <- data.frame(x = 1:100, y = cumsum(rnorm(100)), volume = sample(1:10, 400, replace = TRUE), group = letters[1:4])
plots <- list()
for (j in unique(df$group)){
plot_df <- df[df$group == j, ]
p1 <- ggplot(plot_df, aes(x,y)) +
geom_line() +
facet_wrap(~group) +
xlab("")
p2 <- ggplot(plot_df, aes(x,volume)) +
geom_bar(stat = "identity")
p_out <- plot_grid(p1, p2, align = "v", ncol = 1, rel_heights = c(.7, .3))
plots[[j]] <- p_out
}
do.call(grid.arrange, plots)
Created on 2019-01-25 by the reprex package (v0.2.1)
I've been trying to mimic the output of filled.contour with ggplot's geom_tile and geom_raster. There seems to be some interpolation or something behind the scenes of filled.contour to fill in the gaps, especially in y-axis. Any idea how to make similar, nice looking plot with ggplot?
Data for example can be downloaded here (ShareCSV link).
Code for example:
library("ggplot2")
library("reshape2")
file <- file.choose()
data <- read.csv(file, stringsAsFactors=FALSE, header=TRUE,
colClasses=c("POSIXct", rep("numeric", 12)),
check.names=FALSE)
palette <- colorRampPalette(c("darkblue", "blue", "lightblue1",
"green", "yellow", "red", "darkred"))
# GGplot version
df <- melt(data, id.vars="Time", measure.vars=names(data)[-1])
names(df)[2:3] <- c("Channel", "Value")
df$Channel <- log10(as.numeric(as.character(df$Channel)))
df$Value <- log10(df$Value)
p <- ggplot(data=df, aes(x=Time, y=Channel, fill=Value)) +
# geom_tile() +
geom_raster() +
scale_y_continuous(expand=c(0, 0)) +
scale_x_datetime(expand=c(0, 0)) +
scale_fill_gradientn(colours=palette(100)) +
theme_bw()
p
# Base version
Channel <- log10(as.numeric(names(data[-1])))
Value <- log10(data.matrix(data[, -1]))
filled.contour(x=data$Time, y=Channel, z=Value,
color.palette=palette, nlevels=100)
I tried the following for df and it got pretty close but it's very compute intensive.
library("akima")
interpolation <- with(df, interp(x=Time, y=Channel, z=Value,
xo=seq(min(Time), max(Time), length.out=nrow(data)),
duplicate="mean"))
df<- interp2xyz(interpolation, data.frame=TRUE)
names(df) <- c("Time", "Channel", "Value")
df$Time <- as.POSIXct(df$Time, origin="1970-01-01")
Outcome:
I have data frame like this:
frame <- data.frame("AGE" = seq(18,44,1),
"GROUP1"= c(83,101,159,185,212,276,330,293,330,356,370,325,264,274,214,229,227,154,132,121,83,69,57,32,16,17,8),
"GROUP2"= c(144,210,259,329,391,421,453,358,338,318,270,258,207,186,173,135,106,92,74,56,41,31,25,13,16,5,8))
I want to plot AGE in X-axis and value of GROUP1 and GROUP2 in the Y-axis in the same plot with different colors. And the values should be joined by a smoothened line.
As a first part, I melted the data frame and plotted:
melt <- melt(frame, id.vars = "AGE")
melt <- melt[order(melt$AGE),]
plot(melt$AGE, melt$value)
Here is an alternative solution using dplyr and tidyr packages.
library(dplyr)
library(tidyr)
newframe <- frame %>% gather("variable","value",-AGE)
ggplot(newframe, aes(x=AGE, y=value, color=variable)) +
geom_point() +
geom_smooth()
You could use geom_line() to get lines between the points, but it feels better to use geom_smooth() here. geom_area gives you a shaded area under the lines, but we need to change color to fill.
ggplot(newframe, aes(x=AGE, y=value, fill=variable)) + geom_area()
We can use matplot
matplot(`row.names<-`(as.matrix(frame[-1]), frame[,1]),
ylab='value',type = "l", xlab = "AGE",col = c("red", "blue"), pch = 1)
legend("topright", inset = .05, legend = c("GROUP1", "GROUP2"),
pch = 1, col = c("red", "blue"), horiz = TRUE)
Try,
library(ggplot2)
ggplot(meltdf,aes(x=AGE,y=value,colour=variable,group=variable)) + geom_line()
Is there a more efficient way to present these data in ggplot2? Ideally, I would like them both in one plot. I know this can be achieved in python with matlibplot, but I like the visuals of ggplot2 better.
R code used to generate the plots:
#load libraries
library(ggplot2)
library (gridExtra)
library(scales)
#generate some data plot 1
var_iter <- c(seq(0, 4000, 20))
x <- runif(201,0.877813, 2.283210)
var_loss <- c(sort(x, decreasing = TRUE))
rndm1 <- data.frame(var_iter, var_loss)
#generate some data plot 2
var_iter2 <- c(seq(0, 3500, 500))
x2 <- runif(8,0.1821, 0.6675)
var_acc <- c(sort(x2, decreasing = FALSE))
rndm2 <- data.frame(var_iter2, var_acc)
#plot loss
c <- ggplot(data=rndm1, aes(x=var_iter, y=var_loss)) + geom_line(aes(colour="Log Loss")) +
scale_colour_manual(name='', values=c('Log Loss'='#00BFC4')) + #theme_bw() +
xlab("iterations") + ylab("log loss") + theme(legend.position=c(1,1),legend.justification=c(1,1),
legend.direction="horizontal",
legend.box="horizontal",
legend.box.just = c("top"),
legend.background = element_rect(fill=alpha('white', 0.3)))
#plot accuracy
d <- ggplot(data=rndm2, aes(x=var_iter2, y=var_acc)) + geom_line(aes(colour="Accuracy")) +
scale_colour_manual(name='', values=c('Accuracy'='#F8766D')) + #theme_bw() +
xlab("iterations") + ylab("accuracy") + theme(legend.position=c(0.80, 1),legend.justification=c(1,1),
legend.direction="horizontal",
legend.box="horizontal",
legend.box.just = c("top"),
legend.background = element_rect(fill=alpha('white', 0.3)))
grid.arrange(c, d, ncol=2)
You still can use the same concept of adding a layer on another layer.
ggplot(rndm1, aes(x=var_iter)) +
geom_line(aes(y=var_loss, color="var_loss")) +
geom_line(data=rndm2, aes(x=var_iter2, y=var_acc, color="var_acc"))
Or combine two data frame together and create another variable for color.
# Change the column name, so they can combine together
names(rndm1) <- c("x", "y")
names(rndm2) <- c("x", "y")
rndm <- rbind(rndm1, rndm2)
# Create a variable for color
rndm$group <- rep(c("Log Loss", "Accuracy"), c(dim(rndm1)[1], dim(rndm2)[1]))
ggplot(rndm, aes(x=x, y=y, color=group)) + geom_line()
I wanted to suggest the same idea as the JasonWang, but he was faster. I think it is the way to go (hence I upvoted it myself).
ggplot2 doesn't allow two y axis, for a reason: Plot with 2 y axes, one y axis on the left, and another y axis on the right
It is misleading.
But if you still want to do it. You can do it with base plot or dygraphs (for example):
rndm2$var_iter <- rndm2$var_iter2
rndm2$var_iter2 <- NULL
merged.rndm <- merge(rndm1, rndm2, all = TRUE)
dygraph(merged.rndm) %>% dySeries("var_acc", axis = "y2")
But this will give you points for var_acc, as it has a lot less observations.
You could fill it.
merged.rndm1 <- as.data.frame(zoo::na.approx(merged.rndm))
dygraph(merged.rndm1) %>% dySeries("var_acc", axis = "y2")
Note: this has approximated values, which might not be something you want to do.
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