It doesn't seem to be possible to rotate the labels of an xaxis using grid.xaxis(at=, lab=) by e.g. 90 degrees using a gpar-option.
Anybody knows a workaround apart from creating separate viewports and using grid.text()?
Try this,
grid.xaxis(seq(0,1,by=0.1), vp=viewport(y=1),
edits = gEdit(gPath="labels", rot=90))
Check this document: An Example of Interactive Graphics Editing in Grid
library("grid")
gxa <- xaxisGrob(at = 1:4/5, vp = viewport(w = 0.5, h = 0.01))
gxa <- editGrob(gxa, gPath = "labels", gp = gpar(col = "black"), rot=90)
grid.draw(gxa)
Related
I am trying to rotate one of the labels on my grid.arrange panel figure to look like the axis of all three plots, but this is not working using the methods I am finding online.
When I use a textGrob for control of the font size (which I need to be 24), using this code, I get this figure. I am inserting the rot= 90 argument but it isn't doing anything to the figure.
grid.arrange(d.a.plot1, d.b.plot1, d.c.plot1, ncol = 1, left = textGrob("Probability of remaining availabile", gp=gpar(fontsize=24, rot = 90)), bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))
When I use the standard grid.arrange code to add a rotated label using the code below, the position is fine, but then I can't adjust the font.
grid.arrange(d.a.plot1, d.b.plot1, d.c.plot1, ncol = 1, left = "Probability of remaining availabile", bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))
You just need to take rot = 90 out of gpar and pass it directly to textGrob:
# Simulate the plot grobs:
f <- function() cowplot::as_grob(~plot(rnorm(100), rnorm(100)))
grid.arrange(f(), f(), f(), ncol = 1,
left = textGrob("Probability of remaining availabile", rot = 90,
gp = gpar(fontsize=24)),
bottom = textGrob("Depth(cm)", gp=gpar(fontsize = 24)))
Is there a simple way of taking an arbitrary function with a series of calls to grid.* functions and viewport actions, like the first function below, and getting back a gTree/grob object like the one generated by the second function?
I ask as it's a lot easier to experiment with creating plots stepwise using the grid.* functions than it is to use the rather unwieldy syntax for creating complex gTrees. However then when you need to use your plots within larger plot elements or combined plots I tend to want them in a gTree form and not writing to the plot device on their own.
I've been struggling to grok grid for a while now and I feel like i've missed something even after delving pretty deep into the documentation, it seems like there must be an easier way to create complex gTrees?
library(grid)
plotter <- function(x){
pushViewport(viewport(gp = gpar(fill = "white", col = "black", lwd = 2)))
grid.rect(
width = 0.3, height = 0.8,
gp = gpar(fill = "red")
)
}
grid.newpage()
plotter()
plotter2 <- function(x) {
g <- gTree()
g <- addGrob(
g,
rectGrob(
width = 0.3, height = 0.8,
gp = gpar(fill = "red"),
vp = "vp"
)
)
g$childrenvp <- viewport(name = "vp", gp = gpar(fill = "white", col = "black", lwd = 2))
g
}
grid.newpage()
grid.draw(plotter2())
The grid.grab() function premits you to capture an existing drawing as a gTree when called after the plotting code which produced it.
The grid.grabExpr() function permits the capture of a gTree without plotting it from an expression describing it as below:
library(grid)
plotter <- function(x) {
grid.grabExpr(expr = {
pushViewport(viewport(gp = gpar(fill = "white", col = "black", lwd = 2)))
grid.rect(
width = 0.3, height = 0.8,
gp = gpar(fill = "red")
)
})
}
grid.newpage()
grid.ls(plotter()) # to see the structure of the gTree
grid.draw(plotter())
I am using R to create a number of small graphics that will be saved as PNG files, typically at 50x50 pixels, which for eventual use in a much larger image as icons or markers. As the content changes frequently, it is desirable that these be created programmatically rather than manually.
Because the content is also simple - a few characters of text and some numbers - the grid functions seemed like a straightforward way to tackle this. I don't know grid at all well as I typically use higher-level libraries such as ggplot2. The MRE below lays out what I have already achieved.
This generates output, but I am having problems linking the sizes and scales of viewport and the various grobs to the ultimate PNG file. What I get is the below, which is fine at first glance, but is a 480x480 pixel image, most of which is unused, with the central graphic taking up only a third of the width and height.
That seems logical given the viewport sizing (=.3), but if I enlarge the viewport, then presumably I have to enlarge the text and so on. (I know how to change the png() parameters to adjust the density, number of pixels and so on, but at this point the image itself is the issue.)
The question boils down to how to best generate a decent-quality 50x50 pixel PNG or SVG file from a graphic such as this, created in R, either using grid or some other approach.
library(grid)
grid.newpage()
png(bg = "transparent")
pushViewport(viewport(width=.3, height=.3, clip="off"))
grid.rect(gp=gpar(lty=0, fill="#008000"))
grid.text("15.5", x = unit(0.5, "npc"), y = unit(0.75, "npc"),
just = "center", hjust = NULL, vjust = NULL, rot = 0,
check.overlap = FALSE, default.units = "npc",
name = NULL, gp = gpar(fontsize=48), draw = TRUE, vp = NULL)
grid.text("13h 20m", x = unit(0.5, "npc"), y = unit(0.25, "npc"),
just = "center", hjust = NULL, vjust = NULL, rot = 0,
check.overlap = FALSE, default.units = "npc",
name = NULL, gp = gpar(fontsize=32), draw = TRUE, vp = NULL)
lg <- linesGrob(x = unit(c(0, 1), "npc"),
y = unit(c(0.5, 0.5), "npc"),
gp = gpar(lwd=2))
grid.draw(lg)
dev.off()
magic library may be helpful for that. I used your starting codes to create an empty png file.
library(grid)
grid.newpage()
png(bg = "transparent")
pushViewport(viewport(width=.3, height=.3, clip="off"))
dev.off()
Then I read that png file to put inside the magic codes as below. Actually, there may exist a way to put the png file directly into the magic in your R session without making temporary write - read works. However ,if you have got a lot of files to create and save as png, it is not so important to read an empty png file once. Since it can be used as for all new outputs.
library(magick)
img <- image_read("./desktop/Rplot001.png")
output <- img %>% image_background("#008000") %>% image_resize("50x50") %>%
image_annotate("15.5", size = 17, gravity = "north", location = "+1+4",color = "black", boxcolor = NULL) %>%
image_annotate("13h 20m", size = 11, gravity = "south", location = "+0+7",color = "black", boxcolor = NULL)
image_write(output, path = "./desktop/output.png", format = "png")
It gives a 50x50 png file,
I have been working on Venn Diagrams in GNU R. I have tried using the packages venneuler and VennDiagram. I find that VennDiagram has a lot more granular control, but it seems to lack the documentation to fill in all the details. The closest I can find is this PPT file.
http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3041657/bin/1471-2105-12-35-S4.PPT which I found from the URL: http://www.ncbi.nlm.nih.gov/pmc/articles/PMC3041657/
Here are my issues with using VennDiagram.
For the code
require(VennDiagram)
venn.diagram(list(B = 1:2000, A = 200:400),fill = c("yellow", "blue"),
alpha = c(0.8, 0.8), cex =1.5, cat.pos=0, cat.fontface = 4,
lty = 1, fontfamily =3, filename = "test001.jpeg");
(I had an image here, but since I am new I do not have rights to post the image. Please generate the image from the code above.)
I can make a subset (hence a circle within a circle). But I am not finding a way to do the following:
Make BC to show as the equal of B^C. No, a literal "B^C" does not work. I would think there is a way to relabel the sets in a different property, but I have not seen a way to do it.
To position the labels of B^C and A^C within the sets and not on the outside as currently shown. I tried cat.pos="inner" but that way not a valid property. I also tried cat.pos=c(0,0) in the hope that I could feed it as an X,Y where X & Y are from the center of the circle, but it did not produce any different results.
Thanks to DWin, here is the code to complete my diagram to the exercise.
Suppose that A ⊂ B. Show that Bc ⊂ Ac.
require(VennDiagram)
plot.new()
venn.plot <- venn.diagram(
x = list(B = 1:200, A = 20:40), category.names= expression(B, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5,
cat.pos=0, cat.dist=c(-.1, -.1), filename = NULL) ;
grid.draw(venn.plot); # grid graphic requires explicit print or draw operation
grid.text(expression(B^c),x=0.2,y=0.95)
grid.text(expression(A^c),x=0.16,y=0.95)
grid.text(expression(A^c),x=0.16,y=0.75)
Perhaps something like this:
venn.diagram(list(B = 1:200, A = 20:40), category.names= expression(B^c, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5, cat.pos=0,
cat.dist=c(.1, -.1), cat.fontface = 4,lty = 1, fontfamily =3,
filename = "test001.jpeg")
To get the labels inside the circles, supply 'cat.dist' with negative values. The trick is that the reference point is radial distance from the boundary at 12 o'clock rather than from the center. The documentation says that the category.names argument is interpreted with plotmath syntax. The superscript operation in plotmath is done with the "^" operator. I have here moved the A" inside while leaving the B^c outside to suggest that it is the area outside the B circle that is being labeled. (I also improved the plotting time by making the example smaller.) I tried drawing three labels but that does not seem to "part of the package".
Here's a way you can annotate with grid.text() on the screen device:
plot.new()
venn.plot <- venn.diagram(
x = list(B = 1:200, A = 20:40), category.names= expression(B^c, A),
fill = c("yellow", "blue"), alpha = c(0.8, 0.8), cex =1.5,
cat.pos=0, cat.dist=c(.05, -.1), filename = NULL) ;
grid.draw(venn.plot); # grid graphic requires explicit print or draw operation
grid.text("B",x=0.8)
# then you can save to file
I'm looking for a way to control the line thickness of text plotted in R without having the dimensions of the characters change. Here's an example (not using R):
The middle word has a thickness of twice the top, yet the dimensions are the same (so no scaling happened). The bottom word is actually two words: a red word overlain on a heavy white word, to create color separation (especially useful for annotating a busy plot).
Here's a set of commands I threw together to try and replicate the figure above:
png("font.png",width=1.02, height=1.02, units="in", res=150)
par(ps=10, font=1, bg="light gray", col="black", mai=rep(0.02,4), pin=c(1,1))
plot.new()
box()
text(0.5,0.85,"FONT",cex=1)
text(0.5,0.6,"FONT",cex=2)
text(0.5,0.3,"FONT",cex=2,col="white")
text(0.5,0.3,"FONT",cex=1,col="red")
text(0.5,0.1,"FONT",cex=1, font=2, col="white")
text(0.5,0.1,"FONT",cex=1, font=1, col="red")
dev.off()
giving:
So the effect is the same as changing the font-face to bold, but the size difference is not big enough to be noticeable when overlain. The par help page doesn't appear to have a specific setting for this. Anyone have any ideas?
Note changing size in ggplot2 doesn't produce the effect I want either, last time I checked.
You could try adding multiple versions of the text slightly shifted in a circular pattern,
library(grid)
stextGrob <- function (label, r=0.02, x = unit(0.5, "npc"), y = unit(0.5, "npc"),
just = "centre", hjust = NULL, vjust = NULL, rot = 0, check.overlap = FALSE,
default.units = "npc", name = NULL, gp = gpar(), vp = NULL){
let <- textGrob("a", gp=gp, vp=vp)
wlet <- grobWidth(let)
hlet <- grobHeight(let)
tg <- textGrob(label=label, x=x, y=y, gp=gpar(col="red"),
just = just, hjust = hjust, vjust = vjust, rot = rot,
check.overlap = check.overlap,
default.units = default.units)
tgl <- c(lapply(seq(0, 2*pi, length=36), function(theta){
textGrob(label=label,x=x+cos(theta)*r*wlet,
y=y+sin(theta)*r*hlet, gp=gpar(col="white"),
just = just, hjust = hjust, vjust = vjust, rot = rot,
check.overlap = check.overlap,
default.units = default.units)
}), list(tg))
g <- gTree(children=do.call(gList, tgl), vp=vp, name=name, gp=gp)
}
grid.stext <- function(...){
g <- stextGrob(...)
grid.draw(g)
invisible(g)
}
grid.newpage()
grid.rect(gp=gpar(fill="grey"))
grid.stext("Yeah", gp=gpar(cex=4))
There's a version using base graphics lurking in the archives of R-help, from which this is inspired.
Another option using a temporary postscript file, converted to a shape by grImport,
library(grImport)
cat("%!PS
/Times-Roman findfont
100 scalefont
setfont
newpath
0 0 moveto
(hello) show", file="hello.ps")
PostScriptTrace("hello.ps", "hello.xml")
hello <- readPicture("hello.xml")
grid.rect(gp=gpar(fill="grey"))
grid.picture(hello,use.gc = FALSE, gp=gpar(fill="red", lwd=8, col="white"))
I imagine something similar could be done with a temporary raster graphic file, blurred by some image processing algorithm and displayed as raster below the text.
You could try:
text(...,"FONT", vfont = c('serif','bold'))
Although I'm not sure how you'd do the third version of FONT.