简体   繁体   中英

ggplot2: A mean row in heatmaps

Say I created a heatmap using the function geom_raster() (from ggplot2 ).

What's a smart way to add a row at the bottom of the table showing (in my case) the 'Mean return' for each month on the period considered ?

It would be nice there is some space left between the 1985-2013 period and the row for the average, and maybe police color and 'cases' could be customized.

The core of my code is as follows (the object molten contains the my data, originally a matrix passed through the melt() function of reshape2 .

hm <- ggplot(data = molten, aes(x = factor(Var2, levels = month.abb), y=Var1, fillll=value)) + geom_raster()
hm <- hm + scale_fill_gradient2(low=LtoM(100), mid=Mid, high=MtoH(100))
hm <- hm + labs(fill='% Return')
hm <- hm + geom_text(aes(label=paste(sprintf("%.1f %%", value))), size = 4)
hm <- hm + scale_y_continuous(breaks = 1985:2013)
hm <- hm + xlab(label = NULL) + ylab(label = NULL)
hm <- hm + theme_bw()
hm <- hm + theme(axis.text.x = element_text(size = 10, hjust = 0, vjust = 0.4, angle=90))

图片

It's not very concise, but I think this should do what you need.

You didn't provide a data set, so I just made some up. Also, the LtoM and MtoH functions are not included in any R package I could find, so I did a quick Google search and found them here

The following code produces a plot hm2 with facets to make the "Mean Return" row at the bottom:

require(reshape2)
require(ggplot2)

# Random data
set.seed(100)
casted = data.frame(Var1 = rep(1985:2013, times=12), Var2 = rep(month.abb, each=29), return = rnorm(12*29, 0, 9))
molten = melt(casted, id.vars = c("Var1", "Var2"))

LtoM <-colorRampPalette(c('red', 'yellow' ))
Mid <- "snow3"
MtoH <-colorRampPalette(c('lightgreen', 'darkgreen'))

# Averages
monthly.avg = cbind(Var1 = rep("Mean", 12), dcast(molten, Var2 ~ ., mean))
colnames(monthly.avg)[3] = "Mean"
molten2 = merge(molten, melt(monthly.avg), all.x = TRUE, all.y = TRUE)

# New plot
hm2 = 
  ggplot(data = molten2, aes(x = factor(Var2, levels = month.abb), y=Var1, fill=value)) +
  geom_raster() +
  scale_fill_gradient2(low=LtoM(100), mid=Mid, high=MtoH(100)) +
  labs(fill='% Return') +
  geom_text(aes(label=paste(sprintf("%.1f %%", value))), size = 4) +
  xlab(label = NULL) + ylab(label = NULL) +
  theme_bw() +
  theme(axis.text.x = element_text(size = 10, hjust = 0, vjust = 0.4, angle=90)) +
  facet_grid(variable ~ ., scales = "free_y", space = "free_y") +    # grid layout
  theme(strip.background = element_rect(colour = 'NA', fill = 'NA'), strip.text.y = element_text(colour = 'white'))    # remove facet labels

which gives the following plot:

绘制平均行

How about this:

I created a grid to mock up your data

Main changes, are to precalculate the aggregate and "spacer" data rows, and add to molten, then add scale_y_discrete so you can label the rows, then make sure the format works for the grey spacer bar with no % label (comments in code)

Easier in future if you include the data (or a sample) in the question

情节

require(ggplot2)

molten<-expand.grid(c("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"),1985:2013,0)
colnames(molten)<-c("Var2","Var1","value")
molten$value=(runif(nrow(molten))*60)-30

#create means
means<-aggregate(molten[,c(1,3)], by=list(molten$Var2),FUN=mean, na.rm=TRUE)
colnames(means)<-c("Var2","Var1","value")
means$Var1<-"MEANS"

#create spacer bar
spacer<-means
spacer$Var1<-" "
spacer$value<-NA

#append them to the data
molten<-rbind(molten,spacer,means)


hm <- ggplot(data = molten, aes(x = Var2, y=Var1, fill=value)) + 
geom_raster() +
# replaced your functions for ease of use
scale_fill_gradient2(low="red", mid="yellow", high="green",na.value="grey") +
labs(fill='% Return') +
# don't format the NA vals with %, return blank
geom_text(aes(label=ifelse((is.na(value)),"",paste(sprintf("%.1f %%", value)))), size = 4) +
# make the scale discrete to add labels and enforce order (use a blank space for the spacer)
scale_y_discrete(limits = c("MEANS"," ",1985:2013)) +
xlab(label = NULL) + ylab(label = NULL) +
theme_bw() +
theme(axis.text.x = element_text(size = 10, hjust = 0, vjust = 0.4, angle=90))

hm

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM