barplot design issues - r

I am doing a barplot of 14 columns to represent some data, I set the names.arg option to show as vertical lables, unfortunately, this caused the new vertical lables to overlap with the "sub" and "xlab" options I have. How do I prevent this from happening?
Here's my command:
par(mar=c(6, 5, 4,7.5 ))
barplot(x, main=paste("title1 \n","subtitle"),
names.arg=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14),las=2, sub=("overlapping text1"),
xlab="overlapping text2", col = c("red2","darkorange3"))
Another question on my mind is, I am using a 2-line title in "main" as you can see from the command. Is it possible to make the second line font smaller, whilst keeping the first line in the same format?
Thanks,

One solution to change font size for one of titles, is to use two calls of functions mtext() in different lines with different cex= values and remove main= from barplot(). To overcome problem with overlapping text, mtext() also can be used instead of xlab= and sub=. You just have to find the right line= and increase space around plot with par(mar=..).
x<-sample(letters[1:14],300,replace=TRUE)
par(mar=c(9,3,5,2))
barplot(table(x),
names.arg=paste0("very_long_",1:14),las=2,
col = c("red2","darkorange3"))
mtext(side=3,"Title1",line=2,cex=2)
mtext(side=3,"subtitle",line=1,cex=1.5)
mtext(side=1,"overlapping text1",line=6)
mtext(side=1,"overlapping text2",line=7)

Another option to look at is the staxlab function in the plotrix package.
Also look at the mgp argument to the par function for a way to set the default placement of the axis title.

Related

R Make barchart with unicode symbol instead of bars

I'd like to plot a (kind of) barchart, but rather than using bars, I'd like to use a unicode symbol. Is this possible?
I know how to use a unicode character as a symbol (points); for example:
plot(1,1,pch=-0x0001F3E2, cex=5, col="gray30")
but how can make the symbol substitute the bars?
EDIT:
As suggested by Eric, I'll try to write a minimal reproducible example...
Given variable x:
x <- c(2,3,4,2,1)
barplot(x)
I want to produce a barplot using custom symbols rather than bars. Something like:
plot(1:5,rep(0,5),pch=-0x0001F3E2, cex=x, col="gray30")
The problem is that I am not able to vertical align sysmbols as I can do with text:
plot(1:5,rep(0,5),type="n", ylim=c(0,1),bty="n")
text(1:5,0,"A",cex=c(2,5,3,3,1),adj=c(0.6,0))
So, a sort of solution to my problem, although not ideal, is to use
some custom system font with package extrafont.
For example, using font "Destiny's Little Houses" (http://www.dafont.com/destiny-little-hous.font)
I am able to produce some nice infographics:
plot(1:5,rep(0,5),type="n",ylim=c(0,1),bty="n")
text(1:5,0.1,"A",cex=c(2,5,3,3,1),adj=c(0.6,0),family="Destiny's Little Houses")
So, rather than having bars I have an image whose size changes according to some variable (using "cex").
This is not ideal, first of all because I'd like to be able to import any image (ex. using the png package).
So, is it possible to:
import an image file and use it as the symbol in plot (rather than one of the available sysmbols using pch)?
Vertical align symbols so that I get a kind of custom barchart?
Thanks
António
Here's a somewhat hackish start (might not be helpful as I don't know what your data looks like).
counts <- table(mtcars$gear)
foo <- barplot(counts, col = c("white", "white", "white"), border=c("white"), axes=F, xaxt="n")
points(foo, counts-.5, pch = -0x0001F3E2, cex=2, pos=3)
Remove , axes=F, xaxt="n" to get the labels and axis back.

R how to make legend position independent from graph size

Here is my code; basically I am putting four graphs on the same plot device and putting a legend on each. [edit: I am working with RStudio]
dev.new()
par(mfrow=c(2,2), oma=c(0,0,2,0))
#plot1
plot(parameters...)
par(new=TRUE)
plot(parameters, col="red")
legend("bottomright", c("seed match", "background"), bty="n", lty=c(1,1),
col=c("red","black"), cex=0.8, inset=0)
#plot2
plot(parameters...)
par(new=TRUE)
plot(parameters..., col="red")
legend("bottomright", c("seed match", "background"), bty="n", lty=c(1,1),
col=c("red","black"), cex=0.8,inset=0)
#etc. same for plot2 and plot 3
title("bla bla bla", outer=TRUE)
I have two issues with this.
(1) even though I specified "bottomright", the legend doesn't seem to be aligned to the bottom right, the wider I resize the graph horizontally, the more space there is between the legend and the right of the graph.
(2) the amount of space the legend occupies is inadequate. I tried modifying cex= but that only takes care of font size, the overall space occupied by the legend remains, meaning that the smaller the font, the bigger the space between lines. I would like the legend to be a little less "spread out".
Illustration
This looks sort of OK, although I would like to decrease the space between lines inside the legend:
But when I resize horizontally it doesn't. I would like to tether the legend to the right of the graph.
(1):
As your graphs are all scaled the same way, you could use x and y coordinates to position the legend, not the key words. e.g.:
legend(x = 0.25, y = 35, c("seed match", "background"), bty="n", lty=c(1,1), col=c("red","black"), cex=0.8, inset=0)
(2):
I don't know if there exists a way to manipulate line spacing via legend(), I didn't find one. I always switch to manual generation of the legend via mtext(), abline() and such when the legend has to look really pretty. It is more work but you got control over every aspect of your legend.
One last comment: I guess you want your graph to like nice not on your screen but on some sort of paper or presentation. I always generate graphs with devices like cairo_ps(), svg() or jpeg() (jpeg only on rare occasions because it is raster, not vector-based). These functions give you more control about your graphs than exporting the R Graphics Device. But the way a graph looks changes with the device, each one needs to be configured separately. Better do it only for the one you are going to use in the end.
I hope this helps
Instead of using "bottomright", you could use legend() twice, for each legend element with position values you choose such as
legend(x1,y1,c("seed match"), bty="n", lty=1, col="red", cex=0.8)
for the first one. This way you can choose their position individually and therefore control the spacing between them. I think this solve your two issues.

R-Heatmap.2 Remove huge space left between title and actual heatmap after disabling column dendrogram

I am plotting a 759*12 double matrix twoway.expr.005 using heatmap.2()
library(gplots)
dist2 <- function(x, ...){as.dist(1-cor(t(x), method="pearson"))}
heatmap.2(x=twoway.expr.005,col=bluered(75), main="Heatmap:759 genes\nTwosided Pval<0.05",tracecol= NULL, cexCol=0.8,cexRow=0.5,labCol=labs,distfun=dist2,scale="row",key=F,dendrogram='row',Colv=F)
But because I am setting dendrogram='row' (column dendrogram turned off) and key=F, my heatmap is leaving a huge whitespace between the title of the plot and the actual plot when I try to save it as a PDF.
I tried setting lhei as per the suggestion. I have used lhei=c(1,4) but it still shows me a LOT of space between the title and the plot:
heatmap.2(x=twoway.expr.005,col=bluered(75), main="Heatmap:759 genes\nTwosided Pval<0.05",tracecol= NULL, cexCol=0.8,cexRow=0.5,labCol=labs,distfun=dist2,scale="row",key=F,dendrogram='row',Colv=F,lhei=c(1,4))
Setting lhei=c(1,5) completely throws away the title:
heatmap.2(x=twoway.expr.005,col=bluered(75), main="Heatmap:759 genes\nTwosided Pval<0.05",tracecol= NULL, cexCol=0.8,cexRow=0.5,labCol=labs,distfun=dist2,scale="row",key=F,dendrogram='row',Colv=F,lhei=c(1,5))
I think Heatmap.2 is designed in such a way that the title is always placed above the column dendrogram. So if the column dendrogram is disabled, it leaves an empty space but the position of the title is still above the "disabled" column dendrogram. Is there any way to hack the code so that the title is not placed above the column dendrogram (which may be the solution to this problem)? What else can be done to remove the space between the title & the actual plot?
The lhei argument to heatmap.2 can be used to fix this. It takes a vector of length 2 that represent the relative heights of the rows of the layout of the plot.
Heatmap.2 divides the plot area in to a four blocks using the layout function. Essentially, you want to control the height of the first one relative to the second. To do this, set lhei to something like c(1, 10). This will make the bottom row, which is where the heatmap is, 10 times as tall as the top row which normally has the dendogram for the rows and the color key.
The documentation for layout has more details.
You can use title instead of setting main from within heatmap.2
title("Your title", line= -2).
You can adjust the distance by changing the value of line.
Doesn't help with left to right centering, which is still off without both dendrograms, but you'll be closer.

How to specify a side of the plotting area as the base of a barplot

It is easy to make a barplot in R (using the barplot() function). The default is to have vertical bars that start at the bottom and go up (i.e., the base is at side=1). Furthermore, you can make a barplot with the base on the left (side=1) by using the horiz=T argument. I would like to make a barplot with the base of the bars on the right (side=4).
How do you do this?
How can you make the base at the top (side=3)?
I would prefer to be able to do this with the base graphics, if possible.
One quick option (probably a bit of a kludge) is to just multiply all of your data by -1, then the bars will go down or left from the axis instead of up or right. You might want to supress the x axis and manually put in the values without the negative sign.
Other options are to write your own function that draws the boxes from the axis you choose using the rect or other command.
Or use grid graphics and use a rotated viewport (this would require abandoning the base raphics however).
Edit
Actually there turns out to be a less kludgy way to use the base barplot function, see this example (and modify for your situation).
barplot( 1:5, horiz=TRUE, xlim=c(5,0) )
You will need to replace the 5 in the xlim argument with something based on your data, either the maximum value, the maximum of the sums, the previous times 1.04, etc.
This will still label the bars on the left (if you give it labels), but you can supress that axis and manually put the axis on the right if that is what you prefer.

Plots without titles/labels in R

In R is there any way to produce plots which have no title and which use the space the title would otherwise have taken up?
In plot(), main, sub, xlab, and ylab all default to NULL, but this just leaves blank space where they would have been, ditto for setting them to ''. It would be nice if not including them meant that the entire plot space was utilized rather than leaving extra empty space on the edges. This is all especially relevant in printing plots to file devices like pdf(), png(), etc.
See tip 7 about adjusting the margins.
Excerpt:
To remove the space reserved for labels, use par(mar=...). For example
png(file="notitle.png",width=400, height=350)
par(mar=c(5,3,2,2)+0.1)
hist(rnorm(100),ylab=NULL,main=NULL)
dev.off()
If you're willing to entertain an alternate plotting package, ggplot2 does this automatically when you set xlab/ylab to NULL (and there is no plot title/main by default). For simple plots, just require(ggplot2) and replace plot by qplot.
Really, ggplot2 is the most fun I've had with plotting in years and I can't resist the opportunity to evangelize it to everyone I meet. :-)
With lattice, it's just a matter of setting the xlab, ylab, and main arguments to NULL:
library(lattice)
bwplot(rnorm(100),xlab=NULL,ylab=NULL,main=NULL)
plot(anything, main=NULL)
Still works.
I usually use
par(mar=c(1,1,1,1))
when I keep the border to a minimum.

Resources