I am designing a sheet with multiple plots, but for all the bar plots with only one bar the x-axis label isn't shown.
How can I make the axis label be shown at all my plots?
Here is my result:
Here is my code:
library(utils)
library(RColorBrewer)
library(readr)
library(readxl)
rm(list=ls())
color <- brewer.pal(6,"Spectral")
overlap <- read_excel("overlap.xlsx")
par(mar=c(3,3,1,1),mgp=c(2,0.9,0),xaxs="i", yaxs="i")
overlap.dat <- overlap[overlap$`Countries and areas`=="Pakistan",]
overlap.dat <- t(overlap.dat)
colnames(overlap.dat) = overlap.dat[5,]
overlap.dat <- as.matrix(overlap.dat[-c(1:8,14),])
barplot(overlap.dat, main = "Pakistan", col = color, ylim = c(0,100), xlim = c(0, 8),
cex.names = 0.8, names.arg = colnames(overlap.dat), legend = TRUE,
args.legend = list(x = "topright", y = 100, cex = 0.8, bty = "n"), las = 2 )
But I have solved it already. The problem was that r changed my matrix to a vector for all the single row dataframes.
Here the code how I solved it:
color <- brewer.pal(6,"Spectral")
overlap <- read_excel("overlap.xlsx")
par(mar=c(3,3,1,1),mgp=c(2,0.9,0),xaxs="i", yaxs="i")
overlap.dat <- overlap[overlap$`Countries and areas`=="Pakistan",]
overlap.dat <-as.data.frame(t(overlap.dat))
overlap.dat <- as.matrix(overlap.dat, drop=FALSE)
overlap.dat <- as.matrix(overlap.dat[-c(1:8,14),], drop=FALSE)
colnames(overlap.dat)= overlap[overlap$`Countries and areas`=="Pakistan",]$Year
barplot(overlap.dat, main = "Pakistan", col =color, ylim=c(0,100), xlim=c(0,8),cex.names=0.8, names.arg = colnames(overlap.dat),
legend=TRUE, args.legend = list(x="topright",y=100, cex=0.8,bty="n"), las=2 )
Related
I'm trying to develop a multiplot heatmap.2 saved to a pdf. I'm having some success but the axis labels are getting chopped off. Subplot titles are also desirable but again the labels are getting chopped.
Here's my reproducible code:
library(gridExtra)
library(grid)
library(gridGraphics)
library(gplots)
Col = colorRampPalette(c("red","orange","yellow", "white"))
grab_grob <- function(){
grid.echo()
grid.grab()
}
par(cex.main=0.1, mar = c(1,1,1,1) )
#data<-read.table("heatmap.input.matrix.data.txt")
lmat = rbind(c(2,3),c(4,1),c(4,1))
lwid = c(2.5,4)
lhei = c(0.5,4,3)
labRowvec <- c(rep(NULL, dim(matrix(runif(1000, 1,10),ncol=50))[1]))
labColvec <- c(rep(NULL, dim(matrix(runif(1000, 1,10),ncol=50))[2]))
gl <- lapply(1:12, function(i){
heatmap.2(matrix(runif(1000, 1,10),ncol=50), dendrogram = "none",offsetRow=-0.5, offsetCol=-1,srtCol=0, density="density",
lmat =lmat,lhei = lhei,lwid = lwid, xlab="", ylab = "",labRow = labRowvec,labCol = labColvec,
trace = "none", cexRow = 0.2, cexCol = 0.2, margins = c(0.5,2), scale = "row",Colv = FALSE,Rowv = FALSE,
col = Col,key.title = paste0(i,")"),key.xlab = "year",key.ylab = NA,
keysize = 1, key.par=list(mar=c(1,1, 1, 1)))
grab_grob()
})
grid.newpage()
library(gridExtra)
# margin = theme(plot.margin = unit(c(0.1,0.1,0.1,0.1), "cm"))
# grid.arrange(grobs = lapply(gl, "+", margin),ncol=2,clip=TRUE)
g = arrangeGrob(grobs = gl, ncol=2,clip=TRUE)
ggsave(file="whatever.pdf", g)
Can someone help me maintain the axis labels and add a subplot title?
thanks.
Here's what the code generates:
I'm making stacked boxplots and plots on top of one another using R's layout command in base graphics.
The graphs look great, except that y-axis labels from different plots overlap (highlighted in red circle):
Similar questions are here online, but none of them use layout.
I don't want to expand the space between the plots, I don't think this will look good.
How
I've tried reducing the font size, but the labels still go outside the plot area.
How can I set R's boxplot and plot so that the tick labels do not go above or below the red line, i.e. the max/min y-value, in the image above?
Some example code
legend_space <- -0.26
right <- 10.5
bottom <- 0
left <- 5
top <- 0
cex_main = 1
setEPS()
postscript('figure.eps')
g1 <- c()
g2 <- c()
p <- c()
percent <- c()
sum_p <- c()
sum_percent <- c()
g1_means <- c()
g2_means <- c()
xaxis <- c()
sum_p[1] <- 0.0430904
xaxis[1] <- 2984116
p[1] <- 0.0430904
percent[1] <- -65.1758
sum_percent[1] <- -65.1758
g1[1] <- list(c(47.058824,100.000000,100.000000))
g1_means[1] <- 84.482759
g2[1] <- list(c(13.750000,4.123711,96.000000))
g2_means[1] <- 19.306931
sum_p[2] <- 0.0443229
xaxis[2] <- 2984148
p[2] <- 0.0587825
percent[2] <- -73.8956
sum_percent[2] <- -69.332
g1[2] <- list(c(94.285714,94.736842,100.000000))
g1_means[2] <- 95.145631
g2[2] <- list(c(10.588235,0.000000,92.592593))
g2_means[2] <- 21.250000
sum_p[3] <- 0.0444647
xaxis[3] <- 2984157
p[3] <- 0.124606
percent[3] <- -40.2577
sum_percent[3] <- -60.3056
g1[3] <- list(c(76.315789,94.736842,64.705882))
g1_means[3] <- 83.928571
g2[3] <- list(c(63.529412,0.000000,60.000000))
g2_means[3] <- 43.670886
sum_p[4] <- 0.0393696
xaxis[4] <- 2984168
p[4] <- 0.0310268
percent[4] <- -38.4133
sum_percent[4] <- -54.7893
g1[4] <- list(c(59.459459,57.894737,100.000000))
g1_means[4] <- 64.864865
g2[4] <- list(c(35.294118,6.250000,36.363636))
g2_means[4] <- 26.451613
sum_p[5] <- 0.0304293
xaxis[5] <- 2984175
p[5] <- 0.0344261
percent[5] <- -50.5157
sum_percent[5] <- -54.0582
g1[5] <- list(c(62.500000,94.736842,100.000000))
g1_means[5] <- 85.849057
g2[5] <- list(c(52.873563,6.250000,26.666667))
g2_means[5] <- 35.333333
layout(matrix(c(0,0,1,1,2,2,3,3,4,4), nrow = 5, byrow = TRUE), heights = c(0.2,1,1,1,1.4))
par(mar = c(bottom, left, top, right))
boxplot(g1, xaxt = 'n', range = 0, ylab = '%', ylim = c(0,100), col = 'white', cex.lab=1.5, cex.axis=cex_main, cex.main=cex_main, cex.sub=1.5, xlim = c(0.5,length(g1)+0.5))
title('title', outer = TRUE, line = -1.5)
lines(g1_means, col='dark green', lwd = 3)
par(xpd=TRUE)
legend('topright',inset = c(legend_space,0), c('Control', 'Weighted Mean'), col = c('black','dark green'), lwd = c(1,3))
boxplot(g2, xaxt = 'n', range = 0, main = NULL, ylim = c(0,100), ylab = '%', col = 'gray', cex.lab=1.5, cex.axis=cex_main, cex.main=cex_main, cex.sub=1.5, xlim = c(0.5,length(g2)+0.5))
lines(g2_means, col='dark green', lwd = 3)
par(xpd=TRUE)
legend('topright',inset = c(legend_space,0),c('Case', 'Weighted Mean'), col = c('black','dark green'), lwd = c(1,3))
par(mar = c(bottom, left, top, right))#'mar’ A numerical vector of the form 'c(bottom, left, top, right)’
plot(p, xaxt='n', ylab = 'P', type = 'l', lty = 1, lwd = 3, cex.lab=1.5, cex.axis=1, cex.main=cex_main, cex.sub=1.5, , log = 'y', xlim = c(0.5,length(p)+0.5), ylim = c(min(p,sum_p), max(p, sum_p)))
points(sum_p, xaxt='n', ylab = 'P', type = 'l', col = 'blue', lty = 2, lwd = 3)
legend('topright', inset=c(legend_space,0), c('CpG P', 'Moving P Mean'), col = c('black','blue'), lwd=c(3,3), lty=c(1,2))
par(mar = c(bottom+5, left, top, right))#'mar’ A numerical vector of the form 'c(bottom, left, top, right)’
plot(percent, xaxt='n', ylab = '% Diff.', xlab = 'CpG', type = 'l', lty = 1, lwd = 3, cex.lab=1.5, cex.axis=1, cex.main=cex_main, cex.sub=1.5, xlim = c(0.5,length(percent)+0.5), ylim = c(min(percent, sum_percent), max(percent, sum_percent)))
points(sum_percent, xaxt='n', xlab = 'CpG', type = 'l', col = 'blue', lty = 2, lwd = 3)
par(xpd=TRUE)
legend('topright', inset=c(legend_space,0), c('Percent', 'Moving Mean %'), col = c('black','blue'), lwd=c(3,3), lty=c(1,2))
axis( 1, at=1:length(xaxis), xaxis)
dev.off()
thanks to #count, the solution is simply to use
las=2 in par settings. las=2 sets the labels to be read vertically.
I get a problem for setting the position of legend and wonder if anyone can help.
I follow this example:
http://www.thisisthegreenroom.com/2009/choropleths-in-r/
My code is:
require(maps)
require(ggmap)
library(openxlsx)
rm(list = ls())
map("state", "Arizona")
setwd('M:/SCC/Q-Board')
PM25 <- read.xlsx("PM2.5_Emission_AZ_60 EIS emission sectors.xlsx", sheet = 'Emission_County', colNames = TRUE)
colors = c("#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77",
"#980043")
PM25$colorBuckets <- as.numeric(cut(PM25$PM25, c(0, 5, 10, 20, 30,40, 50)))
map("county",'Arizona', col = colors[PM25$colorBuckets], fill = TRUE,boundary = TRUE, resolution = 0,
lty = 1, projection = "polyconic")
title("PM2.5 Emission by county, 2011")
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
legend("bottom", leg.txt, horiz = F, fill = colors,bty="n",title = 'Unit:1000 tons')
Then, the output figure was shown in below. I try to change the position by setting "top", "left"....
But the legend are still overlap with the figure.
Thank you for your help !
It seems to me that you simply run of out the plotting region. This is very common for spatial plot, which will often occupy a significant amount of your plotting domain. I would split the domain into two: one for spatial plot, the other for legend. The following code does this:
## a function to set up plotting region
## l: ratio of left region
## r: ratio of right region
split.region <- function(l, r) {
layout(matrix(c(rep(1, l), rep(2, r)), nrow = 1))
mai <- par("mai")
mai[2] <- 0.1
mai[4] <- 0
par(mai = mai)
}
# use 80% region for main image
# use 20% region for legend
split.region(4, 1)
## produce your main plot
image(x = 0:10/10, y = 0:10/10, matrix(rbinom(100, 1, 0.3), 10), bty= "n", xaxt = "n", yaxt = "n", ann = FALSE, main = "sample plot")
## set up 2nd plot, with nothing
plot(1:2, bty="n", ann=FALSE, xaxt = "n", yaxt = "n", col = "white")
## add your legend to your second plot
leg.txt <- c("<5", "5-10", "10-20", "20-30", "30-40", ">40")
## place legend at bottom left
legend("bottomleft", leg.txt, horiz = F, pch = 15, col = 1:6, bty="n", title = 'Unit:1000 tons', cex = 1.5)
Adjust l, r until you are satisfied.
I'm using base R plot(), and I want a legend (a color block and key) to show up above (outside) the top right of my plot next to my title (generated using title()).
What's the best way to do this?
Maybe something like this is what you're looking for:
x <- c(1,2,3,4)
y <- c(4,1,3,2)
z <- c(1,2,3,4)
dat <- data.frame(x,y,z)
windows(width = 5, height = 9) #quartz() on Mac
layout(matrix(c(1,2), 2, 1, byrow = TRUE), heights=c(0.5,1))
par(oma = c(4,3,0,0) + 0.1, mar = c(0,0,1,1) + 0.1)
plot(dat$x, y=rep(1,4), type = "n", axes = F, ylab = "", xlab = "")
legend(x = "bottomright", legend = c("y", "z"), fill = c("blue", "red"))
plot(dat$x, dat$y, type = "n", main = "PLOT")
lines(z, col = "red")
lines(y, col = "blue")
Basically this makes two plots, one is just invisible and shortened so all that's displayed is the legend.
You may be able to addtionally tweak the margins around the legend and other graphical parameters (?par) to get the layout better.
Using the sample data below, how can I generate rasters and spatial points plot with the same colorkey as in the "manually" joined plot shown below?
library(rasterVis)
library(raster)
library(colorRamps)
col=colorRampPalette(matlab.like2(255))
s <- stack(replicate(2, raster(matrix(runif(100), 10))))
xy <- data.frame(coordinates(sampleRandom(s, 10, sp=TRUE)),
z1=runif(10), z2=runif(10))
levelplot(s, margin=FALSE, at=seq(0, 1, 0.05),col.regions=col)
x=xy$x;y=xy$y;z=xy$z1
levelplot(z ~ x + y,contour=F, panel = panel.levelplot.points,
margin=FALSE,col.regions=col,
par.settings=list(axis.line=list(lwd=3), strip.border=list(lwd=3)),
cex=1.4, scales=list(x=list(cex=1.7),y=list(cex=1.7)),xlab=list(label="Longitude",cex=2),
ylab=list(label="Latitude",cex=2))
Thanks to #fdestch I was able to generate the following plot using:
latticeCombineGrid(mget(rep("pp", 24)), layout = c(3, 8))
following my comments on printing multiple plots with the same colorkey.
An issue that remains to be clarified:
1) How can one decide on the order of panels? That is, which row & column to place a particular plot just as in levelplot using index.cond.
First of all, you should probably make sure that the breaks in the points plot are identical with those defined in the first levelplot.
## raster plot with colorkey disabled
pr <- levelplot(s, margin = FALSE, at = seq(0, 1, 0.05), col.regions = col,
colorkey = FALSE, xlab = list("Longitude", col = "transparent"))
## points plot
pp <- levelplot(z ~ x + y, panel = panel.levelplot.points, cex = 1.4,
contour = FALSE, margin = FALSE, col.regions = col,
colorkey = list(at = seq(0, 1, .05), width = .6, height = .6),
xlab = "Longitude", ylab = "Latitude")
Please note the definition of a transparent xlab when creating the raster plot. This little workaround comes in quite handy when using downViewport later on to ensure that the actual plot boundaries of pr and pp overlap (feel free to run grid.rect() right after print(pr, newpage = FALSE) to see what I mean).
The actual plot arrangement can then easily be achieved by using viewports from the grid package.
library(grid)
library(lattice)
## initialize new grid device
grid.newpage()
## add raster plot
vp1 <- viewport(x = 0, y = 0, width = .5, height = 1,
just = c("left", "bottom"))
pushViewport(vp1)
print(pr, newpage = FALSE)
## add points plot
downViewport(trellis.vpname("page"))
vp2 <- viewport(x = 1, y = 0, width = .75, height = 1,
just = c("left", "bottom"))
pushViewport(vp2)
print(pp, newpage = FALSE)
Here is my solution using latticeExtra::c.trellis:
library(raster)
library(rasterVis)
s <- stack(replicate(2, raster(matrix(runif(100), 10))))
xy <- data.frame(coordinates(sampleRandom(s, 10, sp=TRUE)),
z1=runif(10), z2=runif(10))
## Define theme and breaks
myTheme <- BTCTheme()
my.at <- seq(0, 1, 0.05)
Plot the Raster* object, using rasterVis::levelplot:
p1 <- levelplot(s, margin=FALSE,
at = my.at,
par.settings = myTheme)
Plot the points, using lattice::levelplot:
p2 <- levelplot(z1 ~ x + y, data = xy,
at = my.at,
panel = panel.levelplot.points,
par.settings = myTheme)
Join them with latticeExtra::c.trellis:
p3 <- c(p1, p2, layout = c(3, 1))
Unfortunately, c.trellis does not assign the strip labels correctly, so you have to define them directly:
update(p3,
strip = strip.custom(factor.levels = c(names(s), "Points")))