I am using ggplot2 to plot maps that have the same extent (i.e. same spatial coverage) but that show different features.
This is how it looks like:
library(raster)
library(reshape2)
library(ggplot2)
# make-up data
r <- raster(system.file("external/test.grd", package="raster"))
s <- stack(r, r**2, r**3, r**4, r**5)
names(s) <- paste0("Field ",seq(1,5))
# convert to data frame
rast.df <- as.data.frame(s, xy=T)
# melt
rast.melt <- melt(rast.df, id.vars = c('x','y'), variable.name="field")
# plot
ggplot() +
geom_raster(data=rast.melt , aes(x=x, y=y, fill=value)) +
facet_wrap(~field) +
scale_fill_continuous(na.value="transparent")
The resulting figure looks quite crappy because there's one single legend for all the maps. Therefore, the maps have no contrast at all.
How can I use individual legends for each facet in the graph above?
Here's an approach with ggarrange from the ggpubr package:
library(ggpubr)
ggarrange(plotlist = lapply(split(rast.melt, rast.melt$field),function(x){
ggplot() + geom_raster(data=x , aes(x=x, y=y, fill=value)) +
scale_fill_continuous(na.value="transparent") +
ggtitle(x$field[1])}))
Related
Using hypothetical data I want to generate these three plots in one plot.
I wonder how I can do it. Is it possible to do it using ggplot2 or fGarch packages?
Here an approach with ggplot2
library("ggplot2")
x <- 0:100
y <- c(dnorm(x, mean=50, sd=10),
dlnorm(x, meanlog=3, sdlog=.7),
dlnorm(100-x, meanlog=3, sdlog=.7))
df <- data.frame(
x=x,
y=y,
type=rep(c("normal", "right skewed", "left skewed"), each=101)
)
ggplot(df, aes(x, y, color=type)) + geom_line()
I have a data.frame which I'd like to scatter plot using ggplot.
The data have 3 factors whose levels I'd like to show in the legend, although the color of the points will only be according to one of these factors (df$group below).
Here's what I have so far:
set.seed(1)
df <- data.frame(x=rnorm(100),y=rnorm(100),
group=LETTERS[sample(5,100,replace=T)],
type=letters[sample(3,100,replace=T)],
background=sample(4,100,replace=T),stringsAsFactors=F)
df$group <- factor(df$group,LETTERS[1:5])
df$type <- factor(df$type,;etters[1:3])
df$background <- factor(df$background,c(1:4))
I manually specify colors:
require(RColorBrewer)
require(scales)
all.colors <- hcl(h=seq(0,(12-1)/(12),length=12)*360,c=100,l=65,fixup=TRUE)
group.colors <- all.colors[1:5]
type.colors <- all.colors[6:8]
background.colors <- all.colors[9:12]
This is what I have for showing the 3 factors in the legend (df$group and df$type):
require(ggplot2)
ggplot(df,aes(x=x,y=y,colour=group,fill=type,alpha=background))+geom_point(cex=2,shape=1,stroke=1)+
theme_bw()+theme(strip.background=element_blank())+scale_color_manual(drop=FALSE,values=group.colors,name="group")+
guides(fill=guide_legend(override.aes=list(colour=type.colors,pch=0)))
So my question is how to get background.colors appear in the legend under "background" rather than the gray scale colors chosen by default that currently appear there.
ggplot(df,aes(x=x, y=y, colour=group, fill=type, alpha=background))+
geom_point(cex=2, shape=1, stroke=1) +
theme_bw() +
theme(strip.background=element_blank()) +
scale_color_manual(drop=FALSE, values=group.colors, name="group") +
guides(fill=guide_legend(override.aes=list(colour=type.colors,pch=0)),
alpha=guide_legend(override.aes=list(colour=background.colors,pch=0)))
I like the stat_ecdf() feature part of ggplot2 package, which I find quite useful to explore a data series. However this is only visual, and I wonder if it is feasible - and if yes how - to get the associated table?
Please have a look to the following reproducible example
p <- ggplot(iris, aes_string(x = "Sepal.Length")) + stat_ecdf() # building of the cumulated chart
p
attributes(p) # chart attributes
p$data # data is iris dataset, not the serie used for displaying the chart
As #krfurlong showed me in this question, the layer_data function in ggplot2 can get you exactly what you're looking for without the need to recreate the data.
p <- ggplot(iris, aes_string(x = "Sepal.Length")) + stat_ecdf()
p.data <- layer_data(p)
The first column in p.data, "y", contains the ecdf values. "x" is the Sepal.Length values on the x-axis in your plot.
We can recreate the data:
#Recreate ecdf data
dat_ecdf <-
data.frame(x=unique(iris$Sepal.Length),
y=ecdf(iris$Sepal.Length)(unique(iris$Sepal.Length))*length(iris$Sepal.Length))
#rescale y to 0,1 range
dat_ecdf$y <-
scale(dat_ecdf$y,center=min(dat_ecdf$y),scale=diff(range(dat_ecdf$y)))
Below 2 plots should look the same:
#plot using new data
ggplot(dat_ecdf,aes(x,y)) +
geom_step() +
xlim(4,8)
#plot with built-in stat_ecdf
ggplot(iris, aes_string(x = "Sepal.Length")) +
stat_ecdf() +
xlim(4,8)
I would like put a bar and a line plot of two separate but related series on the same chart with a legend (the bar plot is of quarterly growth the line plot is of annual growth).
I currently do it with a data.frame in wide format and code like this:
p <- ggplot() +
geom_bar(df, aes(x=Date, y=quarterly), colour='blue') +
geom_line(df, aes(x=Date, y=annual), colour='red')
but I cannot work out how to add a legend, which has a red line labeled 'Annual Growth'; and a blue square labeled 'Quarterly Growth'.
Alternatively, I cannot work out how to have differnt geoms for different series with a long-form data.frame.
UPDATE:
The following example code gets me part of the way towards a solution, but with a really ugly duplicate legend. Still looking for a complete solution ... This approach is based on putting the data in long form and then plotting subsets of the data ...
library(ggplot2)
library(reshape)
library(plyr)
library(scales)
### --- make a fake data set
x <- rep(as.Date('2012-01-01'), 24) + (1:24)*30
ybar <- 1:24
yline <- ybar + 1
df <- data.frame(x=x, ybar=ybar, yline=yline)
molten <- melt(df, id.vars='x', measure.vars=c('ybar', 'yline'))
molten$line <- ifelse(molten$variable=='yline', TRUE, FALSE)
molten$bar <- ifelse(molten$variable=='ybar', TRUE, FALSE)
### --- subset the data set
df.line <- subset(molten, line==TRUE)
df.bar <- subset(molten, bar==TRUE)
### --- plot it
p <- ggplot() +
geom_bar(data=df.bar, mapping=aes(x=x, y=value, fill=variable, colour=variable),
stat='identity', position='dodge') +
geom_line(data=df.line, mapping=aes(x=x, y=value, colour=variable)) +
opts(title="Test Plot", legend.position="right")
ggsave(p, width=5, height=3, filename='plot.png', dpi=150)
And an example plot ...
By use of the subset argument to geoms.
> x=1:10;df=data.frame(x=x,y=x+1,z=x+2)
> ggplot(melt(df),
aes(x,value,color=variable,fill=variable))+
geom_bar(subset=.(variable=="y"),stat="identity")+
geom_line(subset=.(variable=="z"))
I have problems plotting a raster with factor values using ggplot2.
library(ggplot2)
library(raster)
first, load raster data
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
extract coordinates and values
val <- getValues(r)
xy <- as.data.frame(xyFromCell(r,1:ncell(r)))
xy <- cbind(xy,val)
plot the grid using geom_raster(). Everything works fine.
ggplot(xy, aes(x=x, y=y, fill=val)) + geom_raster() + coord_equal()
I don not have a continuous raster, but a classified. Reclass the raster:
r <- reclass(r, c(0,500,1, 500,2000,2))
val <- getValues(r)
xy <- as.data.frame(xyFromCell(r,1:ncell(r)))
xy <- cbind(xy,val)
plot the classified raster. Also OK, but legend is continuous
ggplot(na.omit(xy), aes(x=x, y=y, fill=val)) + geom_raster() + coord_equal()
if I plot the values as factor, the map becomes wrong
ggplot(na.omit(xy), aes(x=x, y=y, fill=factor(val))) + geom_raster() + coord_equal()
Plotting the reclassified plot works for me using R version 2.15.1, ggplot2_0.9.2.1 and raster_2.0-12. If applicable, try updating R, packages, and dependencies. Proceeding from a slightly modified version of your code:
f <- system.file("external/test.grd", package="raster")
r <- raster(f)
r <- reclassify(r, c(0,500,1, 500,2000,2))
val <- getValues(r)
xy <- as.data.frame(xyFromCell(r,1:ncell(r)))
xy <- cbind(xy,val)
ggplot(na.omit(xy), aes(x=x, y=y, fill=val)) + geom_raster() + coord_equal()
p <- ggplot(na.omit(xy), aes(x=x, y=y, fill=factor(val))) +
geom_raster() +
coord_equal()
try(ggsave(plot=p,<some file>,height=8,width=8))
I get:
Note that classify() has been depreciated and reclassify() is its substitute.