I want to adjust the size of the text in the axis labels of the wireframe method in R (found in the lattice package).
It seems like it should just be a matter of specifying
cex.lab=2
as is the case with most other plots. However, this does not increase the font size.
For example:
some_data <- expand.grid(c(1:10), c(1:10))
some_data$z <- sin(some_data$Var1 + some_data$Var2)
wireframe(z~Var1*Var2, some_data, scales=list(arrows=FALSE, cex=1.5), xlab='blah1', ylab='blah2', zlab='blah3')
wireframe(z~Var1*Var2, some_data, scales=list(arrows=FALSE, cex=1.5), xlab='blah1', ylab='blah2', zlab='blah3', cex.lab=4)
should produce a second plot with axis labels 4 times larger than the ones in the first. Instead they are identical.
Two ways, there might be others:
wireframe(z~Var1*Var2, some_data,
trellis.par.set(list(axis.text=list(cex=2))),
scales=list(arrows=FALSE),
xlab='blah1', ylab='blah2', zlab='blah3')
The canonical reference for this is Sarkar's "Lattice" text and this is described in the Parameter System chapter on pages 126-128.
It also appears that you can use nested arguments within scales. Drop the par.settings call and use this instead:
..., scales=list(arrows=FALSE, axis=list(text=list(cex=2))), ...
Related
I'm trying to create a scatter plot + linear regression line in R 3.0.3. I originally tried to create it with the following simple call to plot:
plot(hops$average.temperature, hops$percent.alpha.acids)
This created this first plot:
As you can see, the scales of the Y and X axes differ. I tried fixing this using the asp parameter, as follows:
plot(hops$average.temperature, hops$percent.alpha.acids, asp=1, xaxp=c(13,18,5))
This produced this second plot:
Unfortunately, setting asp to 1 appears to have compressed the X axis while using the same amount of space, leaving large areas of unused whitespace on either side of the data. I tried using xlim to constrain the size of the X-axis, but asp seemed to overrule it as it didn't have any effect on the plot.
plot(hops$average.temperature, hops$percent.alpha.acids, xlim=c(13,18), asp=1, xaxp=c(13,18,5))
Any suggestions as to how I could get the axes to be on the same scale without creating large amounts of whitespace?
Thanks!
One solution would be to use par parameter pty and set it to "s". See ?par:
pty
A character specifying the type of plot region to be used; "s"
generates a square plotting region and "m" generates the maximal
plotting region.
It forces the plot to be square (thus conteracting the side effect of asp).
hops <- data.frame(a=runif(100,13,18),b=runif(100,2,6))
par(pty="s")
plot(hops$a,hops$b,asp=1)
I agree with plannapus that the issue is with your plotting area. You can also fix this within the device size itself by ensuring that you plot to a square region. The example below opens a plotting device with square dimension; then the margins are also set to maintain these proportions:
Example:
n <- 20
x <- runif(n, 13, 18)
y <- runif(n, 2, 6)
png("plot.png", width=5, height=5, units="in", res=200)
par(mar=c(5,5,1,1))
plot(x, y, asp=1)
dev.off()
The R package wordcloud has a very useful function which is called wordlayout. It takes initial positions of words and their respective sizes an rearranges them in a way that they do not overlap. I would like to use the results of this functions to do a geom_text plot in ggplot.
I came up with the following example but soon realized that there seems to be a big difference betweetn cex (wordlayout) and size (geom_plot) since words in graphics package appear way larger.
here is my sample code. Plot 1 is the original wordcloud plot which has no overlaps:
library(wordcloud)
library(tm)
library(ggplot2)
samplesize=100
textdf <- data.frame(label=sample(stopwords("en"),samplesize,replace=TRUE),x=sample(c(1:1000),samplesize,replace=TRUE),y=sample(c(1:1000),samplesize,replace=TRUE),size=sample(c(1:5),samplesize,replace=TRUE))
#plot1
plot.new()
pdf(file="plot1.pdf")
textplot(textdf$x,textdf$y,textdf$label,textdf$size)
dev.off()
#plot2
ggplot(textdf,aes(x,y))+geom_text(aes(label = label, size = size))
ggsave("plot2.pdf")
#plot3
new_pos <- wordlayout(x=textdf$x,y=textdf$y,words=textdf$label,cex=textdf$size)
textdf$x <- new_pos[,1]
textdf$y <- new_pos[,2]
ggplot(textdf,aes(x,y))+geom_text(aes(label = label, size = size))
ggsave("plot3.pdf")
#plot4
textdf$x <- new_pos[,1]+0.5*new_pos[,3]#this is the way the wordcloud package rearranges the positions. I took this out of the textplot function
textdf$y <- new_pos[,2]+0.5*new_pos[,4]
ggplot(textdf,aes(x,y))+geom_text(aes(label = label, size = size))
ggsave("plot4.pdf")
is there a way to overcome this cex/size difference and reuse wordlayout for ggplots?
cex stands for character expansion and is the factor by which text is magnified relative the default, specified by cin - set on my installation to 0.15 in by 0.2 in: see ?par for more details.
#hadley explains that ggplot2 sizes are measured in mm. Therefore cex=1 would correspond to size=3.81 or size=5.08 depending on if it is being scaled by the width or height. Of course, font selection may cause differences.
In addition, to use absolute sizes, you need to have the size specification outside the aes otherwise it considers it a variable to map to and choose the scale itself, eg:
ggplot(textdf,aes(x,y))+geom_text(aes(label = label),size = textdf$size*3.81)
Sadly I think you're going to find the short answer is no! I think the package handles the text vector mapping differently from ggplot2, so you can tinker with size and font face/family, etc. but will struggle to replicate exactly what the package is doing.
I tried a few things:
1) Try to plot the grobs from textdata using annotation_custom
require(plyr)
require(grid)
# FIRST TRY PLOT INDIVIDUAL TEXT GROBS
qplot(0:1000,0:1000,geom="blank") +
alply(textdf,1,function(x){
annotation_custom(textGrob(label=x$label,0,0,c("center","center"),gp=gpar(cex=x$size)),x$x,x$x,x$y,x$y)
})
2) Run the wordlayout() function which should readjust the text, but difficult to see for what font (similarly doesn't work)
# THEN USE wordcloud() TO GET CO-ORDS
plot.new()
wordlayout(textdf$x,textdf$y,words=textdf$label,cex=textdf$size,xlim=c(min(textdf$x),max(textdf$x)),ylim=c(min(textdf$y),max(textdf$y)))
plotdata<-cbind(data.frame(rownames(w)),w)
colnames(plotdata)=c("word","x","y","w","h")
# PLOT WORDCLOUD DATA
qplot(0:1000,0:1000,geom="blank") +
alply(plotdata,1,function(x){
annotation_custom(textGrob(label=x$word,0,0,c("center","center"),gp=gpar(cex=x$h*40)),x$x,x$x,x$y,x$y)
})
Here's a cheat if you just want to overplot other ggplot functions on top of it (although the co-ords don't seem to match up exactly between the data and the plot). It basically images the wordcloud, removes the margins, and under-plots it at the same scale:
# make a png file of just the panel
plot.new()
png(filename="bgplot.png")
par(mar=c(0.01,0.01,0.01,0.01))
textplot(textdf$x,textdf$y,textdf$label,textdf$size,xaxt="n",yaxt="n",xlab="",ylab="",asp=1)
dev.off()
# library to get PNG file
require(png)
# then plot it behind the panel
qplot(0:1000,0:1000,geom="blank") +
annotation_custom(rasterGrob(readPNG("bgplot.png"),0,0,1,1,just=c("left","bottom")),0,1000,0,1000) +
coord_fixed(1,c(0,1000),c(0,1000))
I generate a plot using the package hexbin:
# install.packages("hexbin", dependencies=T)
library(hexbin)
set.seed(1234)
x <- rnorm(1e6)
y <- rnorm(1e6)
hbin <- hexbin(
x = x
, y = y
, xbin = 50
, xlab = expression(alpha)
, ylab = expression(beta)
)
## Using plot method for hexbin objects:
plot(hbin, style = "nested.lattice")
abline(h=0)
This seems to generate an S4 object (hbin), which I then plot using plot.
Now I'd like to add a horizontal line to that plot using abline, but unfortunately this gives the error:
plot.new has not yet been called
I have also no idea, how I can manipulate e.g. the position of the axis labels (alpha and beta are within the numbers), change the position of the legend, etc.
I'm familiar with OOP, but so far I could not find out how plot() handles the object (does it call certain methods of the object?) and how I can manipulate the resulting plot.
Why can't I simply draw a line onto the plot?
How can I manipulate axis labels?
Use lattice version of hex bin - hexbinplot(). With panel you can add your line, and with style you can choose different ways of visualizing hexagons. Check help for hexbinplot for more.
library(hexbin)
library(lattice)
x <- rnorm(1e6)
y <- rnorm(1e6)
hexbinplot(x ~ y, aspect = 1, bins=50,
xlab = expression(alpha), ylab = expression(beta),
style = "nested.centroids",
panel = function(...) {
panel.hexbinplot(...)
panel.abline(h=0)
})
hexbin uses grid graphics, not base. There is a similar function, grid.abline, which can draw lines on plots by specifying a slope and intercept, but the co-ordinate system used is confusing:
grid.abline(325,0)
gets approximately what you want, but the intercept here was found by eye.
You will have more luck using ggplot2:
library(ggplot2)
ggplot(data,aes(x=alpha,y=beta)) + geom_hex(bins=10) + geom_hline(yintercept=0.5)
I had a lot of trouble finding a lot of basic plot adjustments (axis ranges, labels, etc.) with the hexbin library but I figured out how to export the points into any other plotting function:
hxb<-hexbin(x=c(-15,-15,75,75),
y=c(-15,-15,75,75),
xbins=12)
hxb#xcm #gives the x co-ordinates of each hex tile
hxb#ycm #gives the y co-ordinates of each hex tile
hxb#count #gives the cell size for each hex tile
points(x=hxb#xcm, y=hxb#ycm, pch=hxb#count)
You can just feed these three vectors into any plotting tool you normally use.. there is the usual tweaking of size scaling, etc. but it's far better than the stubborn hexplot function. The problem I found with the ggplot2 stat_binhex is that I couldn't get the hexes to be different sizes... just different colors.
if you really want hexagons, plotrix has a hexagon drawing function that i think is fine.
I created a simple Dotplot() using this data:
d <- data.frame(emot=rep(c("happy","angry"),each=2),
exp=rep(c("exp","non-exp"),2), accuracy=c(0.477,0.587,0.659,0.736),
Lo=c(0.4508,0.564,0.641,0.719), Hi=c(0.504,0.611,0.677,0.753))
and the code below:
library(Hmisc)
Dotplot(emot ~ Cbind(accuracy, Lo, Hi), groups=exp, data=d,
pch=c(1,16), aspect = "xy", par.settings = list(dot.line=list(col=0)))
What I want to do is to DECREASE the distance between y-axis ticks and decrease the distance between plot elements as well - so that happy/angry horizontal error lines will get closer to each other. I know I could probably achieve that by playing with scales=list(...) parameters (not sure how yet), but I would have to define labels again, etc. Is there a quicker way to do it? It seems like such a simple thing to solve, but I'm stuck.
Despite the fact that Hmisc ::Dotplot is using lattice, just adding a ylim argument seems to do the trick.You can figure out the default scale since those two values were factors with underlying 1/2 values:
Dotplot(emot ~ Cbind(accuracy, Lo, Hi), groups=exp, data=d, ylim=c(0,3),
pch=c(1,16), aspect = "xy", par.settings = list(dot.line=list(col=0)))
I'm using goodfit from vcd package to produce goodness of fit plots.
I would like to add a legend stating the bars are the actual counts and the dots (connected by the line) are the fit using e.g. Poisson and ML.
legend does not work. How can I easily add a legend to this plot?
Thanks!
The plot function for goodfit objects is using the grid graphics system (see ?rootogram and getAnywhere(rootogram.default)).
You have two options:
use the rather limited grid.legend function (from package grid).
embed a base graphics legend in the grid plot using the gridBase package.
Here is a simple example for the first option:
library("vcd")
dummy <- rnbinom(200, size=1.5, prob=0.8)
gf <- goodfit(dummy, type="nbinomial", method="MinChisq")
plot(gf)
pushViewport(viewport(x=unit(0.8, "npc"),
y=unit(0.8, "npc"),
width=stringWidth("Legend x"),
height=unit(6, "line"),
name="vp1"))
grid.legend(labels=c("Legend 1", "Legend 2"), pch=1:2)
popViewport()
Modifying #rcs's answer to use grid_legend (in the vcd package along with goodfit), which is intended for users (grid.legend is an undocumented internal function), and to show a legend specifically geared to this plot. It would be nice to use fill=c(NA,"gray") as in legend in base graphics, but it's not implemented in grid_legend.
library("vcd")
dummy <- rnbinom(200, size=1.5, prob=0.8)
gf <- goodfit(dummy, type="nbinomial", method="MinChisq")
plot(gf)
grid_legend(x=unit(0.8, "npc"),
y=unit(0.8, "npc"),
labels=c("est NBinom (MinChiSq)","obs"),
title="",
pch=c(16,15),col=c("red","gray"))
It is hard to tell without a specific example (AFAIK it is not a limitation with goodfit), but I would check a few things with legend:
You can place a legend with "topright", "bottomleft", etc for the argument x.
You can query the x and y axis limits with par("usr"). If the plot is in log scale and you want to place the legend at the maximum value of y, you have to use 10^par("usr")[4], and so on.
Pass the argument xpd=NA to see if you are placing the legend outside of the plotting region and see if you need to set xjust or yjust.