I need to remove the ticks and major line from a generated axis using grid.yaxis.
According to ?grid.yaxis there is an "edits" parameter that will let me configure the "major", "ticks" and "labels".
However, I cant find how to use the edits parameter.
Here's some example code that will draw an axis in the center.
grid_test_axis <- function ()
{
grid.newpage()
vplayout <- function(x,y)
viewport(layout.pos.row=x,layout.pos.col=y)
pushViewport( viewport( layout=grid.layout( nrow=3, ncol=3, widths=c(1,1,1), heights=c(1,1,1)) ) )
pushViewport(viewport(layout.pos.col=1, clip="on"))
grid.rect(gp=gpar(fill="red"))
popViewport()
pushViewport(viewport(layout.pos.col=3, clip="on"))
grid.rect(gp=gpar(fill="brown"))
popViewport()
pushViewport(viewport(layout.pos.row=1,layout.pos.col=2))
grid.rect(gp=gpar(fill="yellow"))
popViewport()
pushViewport(viewport(layout.pos.row=3,layout.pos.col=2))
grid.rect(gp=gpar(fill="blue"))
popViewport()
pushViewport(viewport(layout.pos.row=2,layout.pos.col=2))
pushViewport(viewport(layout=grid.layout(nrow=1, ncol=2)))
pushViewport(viewport(layout.pos.row=1,layout.pos.col=2))
grid.yaxis(main=TRUE, at=seq(.1, .9, length=5))
popViewport(3)
}
I would like to just stay with the numbers, not the ticks or major line.
Thanks.
Try this:
grid.yaxis(name="ya", main=TRUE, at=seq(0.1, 0.9, length=5))
grid.remove(gPath("ya", "ticks"))
grid.remove(gPath("ya", "major"))
Related
I would like to plot grid objects and base R objects on the same png. The package I am using (meta) uses the grid graphics system.
I would like to use mfrow for this if possible, as it is what I am using elsewhere.
If I plot:
png("test.png",width=297,height=210,units="mm",res=300)
par(mfrow=c(2,2))
plot(1,1)
plot(1,1)
plot(1,1)
plot(1,1)
dev.off()
Everything works fine.
However if I plot:
library(meta)
m <- metaprop(4:1, c(10, 20, 30, 40))
png("test.png",width=297,height=210,units="mm",res=300)
par(mfrow=c(2,2))
plot(1,1)
forest(m,new=F)
plot(1,1)
forest(m,new=F)
dev.off()
Things aren't right as the forest plots try to take up the whole page rather than being restricted to their corners.
Thanks in advance for your help
I bet it behaves similar to heatmap() plots, see here.
Possible example for a solution from the post (didn't test):
--snip // Citation (Dr Paul Murrell)--
library(gridGraphics)
grid.newpage()
pushViewport(viewport(0, .5, .5, .5, just=c("left", "bottom")))
grid.echo(function() { heatmap(test) }, newpage=FALSE)
popViewport()
pushViewport(viewport(.5, 0, .5, .5, just=c("left", "bottom")))
grid.echo(function() { heatmap(test) }, newpage=FALSE)
popViewport()
--snip--
Modifying this answer, you can combine them into a plot, but I think the margins and settings for forest() needs to be optimized so that the titles etc can be seen properly:
library(gridBase)
library(gridExtra)
layout(matrix(c(1,2),nrow=1),widths=c(1,3))
par(mar=c(2.5,2.5,2.5,2.5))
plot(1,1)
plot.new()
vps <- baseViewports()
pushViewport(vps$figure)
vp1 <-plotViewport()
forest(m,new=FALSE)
popViewport()
I want to make a plot consisting of multiple plots consisting of multiple plots, say a 5x2 grid with three plots in each cell. To be more precise, what I need is not just one figure but finding a way of using my plotting function multiple times in a single plot.
I have written a function that uses layout to stack plots, with a common axis in outer margin. I actually need it for seqIplot and seqdplot functions from the TraMineR package, but as far as I understand the problem is not related to those, so here is a minimal working example with barplot.
stackedplot <- function(data){
layout(matrix(c(1:3), nrow=3))
par(mar=c(0,0,0,0), oma=c(4,1,1,1), mgp=c(3,0.5,0), cex=1)
barplot(data[[1]], axes=F, xlab="", ylab="", horiz=TRUE)
barplot(data[[2]], axes=F, xlab="", ylab="", horiz=TRUE)
barplot(data[[3]], axes=F, xlab="", ylab="", horiz=TRUE)
axis(1, at=c(0:10)/10, outer=TRUE)
mtext("Label", line=2, side=1)
}
stackedplot(list(1:10, 10:1, rep(1,10)))
What I would like to do is to then use something like layout again and use stackedplot for the grids of the layout, i.e. something like this (which, of course, does not work):
layout(matrix(c(1:2), nrow=1))
stackedplot(list(1:10, 10:1, rep(1,10)))
stackedplot(list(rep(1,10), 1:10, 10:1))
I have tried split.screen, with no success:
split.screen(c(1,2))
screen(1)
stackedplot(list(1:10, 10:1, rep(1,10)))
screen(2)
stackedplot(list(rep(1,10), 1:10, 10:1))
close.screen(all = TRUE)
I also tried grid package, but apparently it is not compatible with base graphics.
grid.newpage()
pushViewport(viewport(x=0, y=0, width=0.5, height=1,
default.units="native"))
print(stackedplot(list(1:10, 10:1, rep(1,10))), newpage=FALSE)
pushViewport(viewport(x=0.5, y=0, width=0.5, height=1,
default.units="native"))
print(stackedplot(list(rep(1,10), 1:10, 10:1)), newpage=FALSE)
After more research and some help I am now answering my own question in case it would be useful to someone else.
Nested layouts can be created with the grid package, which can be used for base graphics using the gridBase package. The function for the stacked plots is written as follows.
library(grid)
library(gridBase)
stackedplot <- function(data, main=""){
top.vp <- viewport(layout=grid.layout(nrow=5, ncol=1,
heights=unit(c(3, 1, 1, 1, 5),
c("lines", "null", "null", "null", "lines"))),
width=unit(0.9, "npc"))
title <- viewport(layout.pos.row=1, layout.pos.col=1, name="title")
p1 <- viewport(layout.pos.row=2, layout.pos.col=1, name="plot1")
p2 <- viewport(layout.pos.row=3, layout.pos.col=1, name="plot2")
p3 <- viewport(layout.pos.row=4, layout.pos.col=1, name="plot3")
xaxis <- viewport(layout.pos.row=5, layout.pos.col=1, name="xaxis")
splot <- vpTree(top.vp, vpList(title, p1, p2, p3, xaxis)) # Defining the hierarchy of the viewports
pushViewport(splot) # Creating viewports for plotting with the definitions of splot
upViewport() # Navigating up in the viewport tree
downViewport("plot1") # Navigating down in the viewport tree, searching for viewport "plot1"
grid.rect() # Plotting a rectangle (borders for the viewport)
par(plt=gridPLT(), new=TRUE) # Taking the dimensions of the viewport for a base graphics plot
# Adding plot to an existing plot
barplot(data[[1]], axes=FALSE, xlab="", ylab="", horiz=TRUE)
upViewport()
downViewport("plot2")
grid.rect()
par(plt=gridPLT(), new=TRUE)
barplot(data[[2]], axes=FALSE, xlab="", ylab="", horiz=TRUE)
upViewport()
downViewport("plot3")
grid.rect()
par(plt=gridPLT(), new=TRUE)
barplot(data[[3]], xlab="", ylab="", horiz=TRUE)
upViewport()
downViewport("xaxis")
grid.text("X label", y = unit(2, "lines"))
upViewport()
downViewport("title")
grid.text(main, y = unit(1, "lines"))
upViewport(2)
}
The function first describes a viewport (of 90% of the window's width) that is divided into a 5x1 grid of viewports with differing heights. Each viewport in the grid is given a name that can be later called. The tree of viewports (splot) is described with vpTree which defines the hierarchical structure of the viewports. After describing the viewports those are actually prepared for plotting with pushViewport.
Now each named viewport is first seeked and then opened for plotting with upViewport (which goes up in the viewport tree) and downViewport (which seeks for the requested viewport down in the viewport tree).
For plotting base graphics, gridPLT is needed here (alternatively gridFIG or gridOMI can be used, see the manual of gridBase for further info). After that any base graphics function can be used to plot into the current viewport.
After the requested plots, upViewport(2) is used to navigate back to the root (2 viewports up in the hierarchy).
Now the stackedplot function can be called multiple times in another grid as follows.
opar <- par(no.readonly=TRUE) # Saving graphical parameters
plot.new() # Needed for par(new=TRUE) in stackedplot()
multitop.vp <- viewport(layout=grid.layout(1,2), width = unit(0.95, "npc"))
pl1 <- viewport(layout.pos.col=1, layout.pos.row=1, name="A")
pl2 <- viewport(layout.pos.col=2, layout.pos.row=1, name="B")
vpall <- vpTree(multitop.vp, vpList(pl1,pl2))
pushViewport(vpall)
upViewport()
downViewport("A")
stackedplot(data=list(1:10,10:1,rep(10,10)),main="A")
upViewport()
downViewport("B")
stackedplot(data=list(10:1,rep(10,10),1:10),main="B")
upViewport(2)
par(opar) # Returning the graphical parameters saved earlier
The grid-package has a special tool for generating axis. It writes the axis outside the current viewport and the height using grobHeight is therefore considered to be 0mm. Unfortunately I need to make space for the axis and I want to know the exact height of the object. Below is an example that illustrates the problem:
library(grid)
plotColorBar <- function () {
grid.newpage()
xg <- xaxisGrob(at=c(0,.25,.5,.75, 1),
label= sprintf("%d %%", c(0,.25,.5,.75, 1)*100),
main=FALSE)
bar_layout <- grid.layout(nrow=3, ncol=3,
heights = unit.c(unit(.80, "npc"),
grobHeight(xg),
unit(.2, "npc") - grobHeight(xg)),
widths = unit.c(unit(.25, "npc"),
unit(1, "npc") -
unit(.5, "npc"),
unit(.25, "npc")))
pushViewport(viewport(layout=bar_layout, name="Bar_layout"))
pushViewport(viewport(layout.pos.row=3,
layout.pos.col=2,
name="Color_bar"))
grid.draw(xg)
bar_clrs <- colorRampPalette(c("red", "blue"), space="Lab")(101)
grid.raster(t(as.raster(bar_clrs)), width=1, height=1, interpolate=FALSE)
popViewport()
pushViewport(viewport(layout.pos.row=1,
layout.pos.col=1:3,
name="Main_exc_bar"))
grid.rect(gp=gpar(col="black", fill="#00000022"))
grid.text("Coool")
popViewport()
}
png(filename="axisWihtoutHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
Gives the following image:
Notice that the grey area covers the axis text. When I try convertY(grobHeight(xg), "mm") it returns 0mm.
Now applying the #baptiste recommended fix improves the image slightly:
heightDetails.xaxis = function(x) do.call(sum, lapply(x$children, grobHeight))
png(filename="axisWihtHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
As you can see the text for some reason is twice the height. Adjusting this manually through the following option although this does feel a little clumsy:
heightDetails.xaxis = function(x) {
grobHeight(x$children$ticks) +
grobHeight(x$children$labels) +
grobHeight(x$children$labels)
}
png(filename="axisWihtDoubleHeight.png", width=250, height=250, res=96)
plotColorBar()
dev.off()
Final solution
As suggested it seems that unit(1.5*cex, "line") does the job nicely:
heightDetails.xaxis = function(x) {
cex <- 1
if (!is.null(x$children$labels$gp$cex))
cex <- x$children$labels$gp$cex
grobHeight(x$children$ticks) +
unit(1.5*cex, "line")
}
you'll want to define a heightDetails method for the gTree, something along those lines
heightDetails.xaxis = function(x) do.call(sum, lapply(x$children, grobHeight))
I am trying to to add color-gradient bar below the network graph I draw using igraph. For some reason, the axis label of the color-gradient bar can't be shown. However , when I draw the color-gradient bar alone without the network graph, the axis label is perfectly shown. Any suggestion ?
colorstrip <- function(colors) {
count <- length(colors)
m <- matrix(1:count, count, 1)
par(mai=c(5, 50, 30, 50), cex.axis=2, ann=T, tck=-1)
image(m, col=colors, ylab="", axes=FALSE)
axis(side=3, at=seq(from=-0.165, to=1.22, by=0.332),
labels=letters[1:5])
}
library(igraph)
g <- graph.ring(10)
pdf("test_igraph.pdf", width=200, height=200)
layout(matrix(c(1,2), nrow=2), heights=c(2,0.5))
plot(g)
colorstrip(c("red", "mediumseagreen", "yellow", "blue"))
dev.off()
Original code was here
The labels are there, but they are very tiny. Zoom in in your PDF viewer and then you will see them.
The reason for them being tiny is that the plot itself is huge. For pdf() width and height is in inches, so you have a 200 in times 200 in figure. The solution is to make the figure smaller (or the letters bigger, but I guess you don't want to have a huge figure anyway):
colorstrip <- function(colors) {
count <- length(colors)
m <- matrix(1:count, count, 1)
par(mai=c(0.2, 2, 1, 2), cex.axis=2, ann=T, tck=-1)
image(m, col=colors, ylab="", axes=FALSE)
axis(side=3, at=seq(from=-0.165, to=1.22, by=0.332),
labels=letters[1:5])
}
library(igraph)
g <- graph.ring(10)
pdf("test_igraph.pdf", width=7, height=7)
layout(matrix(c(1,2), nrow=2), heights=c(2,0.5))
plot(g)
colorstrip(c("red", "mediumseagreen", "yellow", "blue"))
dev.off()
So this has nothing to do with igraph. Actually, even if you just plot the color strip, you will not see the labels.
I'm trying to add some text to the right hand side of a horizontal barplot at the same heights as each bar, however, both text() and axis() don't seem to plot this at the heights corresponding to each bar.
Here's a similar barplot
x <- runif(10, 0,1)
y <- matrix(c(x, 1-x), nrow=2, ncol=10, byrow=TRUE)
barplot(y, horiz=TRUE, beside=FALSE, names.arg=seq(1,10,1), las=1, xlim=c(0, 1.2))
Neither of these two options align properly, how does the scaling work here?
axis(4, at=seq(1,10,1), labels=seq(1,10,1))
text(1.1, seq(1,10,1), labels=seq(1, 10, 1))
By chacking the documentation of barplot, you can see that it has an invisible return value: the midpoints of the bars. You can use those to add additional information to the plot.
x <- runif(10, 0,1)
y <- matrix(c(x, 1-x), nrow=2, ncol=10, byrow=TRUE)
bp <- barplot(y, horiz=TRUE, beside=FALSE, names.arg=seq(1,10,1), las=1,
xlim=c(0, 1.2))
text(x, bp, signif(x,2), pos=4)
bp