for (i in 1:1000){
fit<-try(lm(y~x,dataset))
results<- ifelse(class(fit)=="try-error", NA, fit$coefficients)
}
Tuesday, May 6, 2008
Error capture
In a recent post to r-sig-ecology, Mike Colvin suggested the following to capture errors within a loop:
Tuesday, March 18, 2008
Plotting contours

Plenty of packages allow you to plot contours of a "z" value; however, I wanted to be able to plot a specific density contour of a sample from a bivariate distribution over a plot that was a function of the x and y parameters. The example only plots the density of x and y; however, if you set plot.dens=FALSE, the contours will be added to the active display device (i.e., over an image(x,y,function(x,y){...})).
This function also lets you specify the line widths and types for each of the contours.
###########################################
## drawcontour.R
## Written by J.D. Forester, 17 March 2008
###########################################
##This function draws an approximate density contour based on
##empirical, bivariate data.
##change testit to FALSE if sourcing the file
testit=TRUE
draw.contour<-function(a,alpha=0.95,plot.dens=FALSE, line.width=2, line.type=1, limits=NULL, density.res=300,spline.smooth=-1,...){
##a is a list or matrix of x and y coordinates (e.g., a=list("x"=rnorm(100),"y"=rnorm(100)))
## if a is a list or dataframe, the components must be labeled "x" and "y"
## if a is a matrix, the first column is assumed to be x, the second y
##alpha is the contour level desired
##if plot.dens==TRUE, then the joint density of x and y are plotted,
## otherwise the contour is added to the current plot.
##density.res controls the resolution of the density plot
##A key assumption of this function is that very little probability mass lies outside the limits of
## the x and y values in "a". This is likely reasonable if the number of observations in a is large.
require(MASS)
require(ks)
if(length(line.width)!=length(alpha)){
line.width <- rep(line.width[1],length(alpha))
}
if(length(line.type)!=length(alpha)){
line.type <- rep(line.type[1],length(alpha))
}
if(is.matrix(a)){
a=list("x"=a[,1],"y"=a[,2])
}
##generate approximate density values
if(is.null(limits)){
limits=c(range(a$x),range(a$y))
}
f1<-kde2d(a$x,a$y,n=density.res,lims=limits)
##plot empirical density
if(plot.dens) image(f1,...)
if(is.null(dev.list())){
##ensure that there is a window in which to draw the contour
plot(a,type="n",xlim=limits[1:2],ylim=limits[3:4],...)
}
##estimate critical contour value
## assume that density outside of plot is very small
zdens <- rev(sort(f1$z))
Czdens <- cumsum(zdens)
Czdens <- (Czdens/Czdens[length(zdens)])
for(cont.level in 1:length(alpha)){
##This loop allows for multiple contour levels
crit.val <- zdens[max(which(Czdens<=alpha[cont.level]))]
##determine coordinates of critical contour
b.full=contourLines(f1,levels=crit.val)
for(c in 1:length(b.full)){
##This loop is used in case the density is multimodal or if the desired contour
## extends outside the plotting region
b=list("x"=as.vector(unlist(b.full[[c]][2])),"y"=as.vector(unlist(b.full[[c]][3])))
##plot desired contour
line.dat<-xspline(b,shape=spline.smooth,open=TRUE,draw=FALSE)
lines(line.dat,lty=line.type[cont.level],lwd=line.width[cont.level])
}
}
}
##############################
##Test the function
##############################
##generate data
if(testit){
n=10000
a<-list("x"=rnorm(n,400,100),"y"=rweibull(n,2,100))
draw.contour(a=a,alpha=c(0.95,0.5,0.05),line.width=c(2,1,2),line.type=c(1,2,1),plot.dens=TRUE, xlab="X", ylab="Y")
}
Monday, February 4, 2008
Drop unused factor levels
When creating a subset of a dataframe, I often exclude rows based on the level of a factor. However, the "levels" of the factor remain intact. This is the intended behavior of R, but it can cause problems in some cases. I finally discovered how to clean up levels in this post to R-Help. Here is an example:
Another way to deal with this is to use the dropUnusedLevels() command in the Hmisc library. The only issue here is that behavior is changed globally which may have undesired consequences (see the post listed above).
****UPDATE****
As Jeff Hollister mentions in the comments, there is another way to do this:
Yet another way, if you are working with data frames that by default convert characters into factors, was suggested on r-sig-ecology by Hadley Wickham:
> a <- factor(letters)
> a
[1] a b c d e f g h i j k l m n o p q r s t u v w x y z
Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z
## Now, even though b only includes five letters,
## all 26 are listed in the levels
> b <- a[1:5]
> b
[1] a b c d e
Levels: a b c d e f g h i j k l m n o p q r s t u v w x y z
## This behavior can be changed using the following syntax:
> b <- a[1:5,drop = TRUE]
> b
[1] a b c d e
Levels: a b c d e
Another way to deal with this is to use the dropUnusedLevels() command in the Hmisc library. The only issue here is that behavior is changed globally which may have undesired consequences (see the post listed above).
****UPDATE****
As Jeff Hollister mentions in the comments, there is another way to do this:
a<-factor(letters)
b<-factor(a[1:5])
Yet another way, if you are working with data frames that by default convert characters into factors, was suggested on r-sig-ecology by Hadley Wickham:
options(stringsAsFactors = FALSE)
a <-data.frame("alpha"=letters)
b<-a[1:5]
Thursday, November 29, 2007
Convert factors to numbers
If you have a vector of factors it is easy to get the factor level; however, I always forget how to extract the factor value. I ran into the answer here.
**UPDATE**
And another method mentioned in the comments (that I like better):
> as.numeric(as.character(x))
> x<-factor(c(round(rnorm(10),2),"A","B",NA))
> x
[1] 1.61 1.12 1.26 0.09 -0.13 0.16 -0.03 -0.1 0.09 -0.47
[11] A B
Levels: -0.03 0.09 -0.1 -0.13 0.16 -0.47 1.12 1.26 1.61 A B
> as.numeric(x)
[1] 9 7 8 2 4 5 1 3 2 6 10 11 NA
> as.numeric(levels(x)[x])
[1] 1.61 1.12 1.26 0.09 -0.13 0.16 -0.03 -0.10 0.09 -0.47
[11] NA NA NA
Warning message:
NAs introduced by coercion
**UPDATE**
And another method mentioned in the comments (that I like better):
> as.numeric(as.character(x))
Thursday, November 15, 2007
Preparing plots for publication
The plotting capabilities of R are excellent; however, when I am preparing a figure for publication, I often need to combine multiple plots or add objects (e.g., arrows or text) to an existing plot. While this can be accomplished in R, my patience for tweaking layout parameters tends to run out quickly. I searched around and found a nice solution using open source software (an example with Matlab plots is described here).
1) Create the desired figure in R and export as an eps file:
2) Install the necessary software on your computer, and then convert the image file to one more easily edited.
3) Edit the new file myfig2.obj in tgif.
1) Create the desired figure in R and export as an eps file:
library(ggplot2)
postscript("myfig.eps",horizontal=FALSE, paper="special",height=10,width=10)
qplot(x,y,data=mydat)
dev.off()
2) Install the necessary software on your computer, and then convert the image file to one more easily edited.
#install software
sudo aptitude install pstoedit tgif
#clean up the eps file so it is more easily read
eps2eps myfig.eps myfig2.eps
#convert the eps file to a tgif object
pstoedit -f tgif myfig2.eps myfig2.obj
3) Edit the new file myfig2.obj in tgif.
Thursday, October 18, 2007
Approximate sunrise and sunset times
This function is not perfect, but it does a reasonable job estimating sunrise and sunset times for my field site. If more accurate data are required, try here. Note, the command to calculate day of year is: strptime(x, "%m/%d/%Y")$yday+1
suncalc<-function(d,Lat=48.1442,Long=-122.7551){ ## d is the day of year ## Lat is latitude in decimal degrees ## Long is longitude in decimal degrees (negative == West) ##This method is copied from: ##Teets, D.A. 2003. Predicting sunrise and sunset times. ## The College Mathematics Journal 34(4):317-321. ## At the default location the estimates of sunrise and sunset are within ## seven minutes of the correct times (http://aa.usno.navy.mil/data/docs/RS_OneYear.php) ## with a mean of 2.4 minutes error. ## Function to convert degrees to radians rad<-function(x)pi*x/180 ##Radius of the earth (km) R=6378 ##Radians between the xy-plane and the ecliptic plane epsilon=rad(23.45) ##Convert observer's latitude to radians L=rad(Lat) ## Calculate offset of sunrise based on longitude (min) ## If Long is negative, then the mod represents degrees West of ## a standard time meridian, so timing of sunrise and sunset should ## be made later. timezone = -4*(abs(Long)%%15)*sign(Long) ## The earth's mean distance from the sun (km) r = 149598000 theta = 2*pi/365.25*(d-80) z.s = r*sin(theta)*sin(epsilon) r.p = sqrt(r^2-z.s^2) t0 = 1440/(2*pi)*acos((R-z.s*sin(L))/(r.p*cos(L))) ##a kludge adjustment for the radius of the sun that = t0+5 ## Adjust "noon" for the fact that the earth's orbit is not circular: n = 720-10*sin(4*pi*(d-80)/365.25)+8*sin(2*pi*d/365.25) ## now sunrise and sunset are: sunrise = (n-that+timezone)/60 sunset = (n+that+timezone)/60 return(list("sunrise" = sunrise,"sunset" = sunset)) }
Sunday, October 14, 2007
Convert polar coordinates to Cartesian
When I want to calculate the coordinates of a location (e.g., a nest or burrow) based on distance and bearing from a grid point, this function helps me avoid writing down SOH-CAH-TOA every time. Just note that the bearing in this case is from the grid point (known location) to the unknown location.
polar2cart<-function(x,y,dist,bearing,as.deg=FALSE){
## Translate Polar coordinates into Cartesian coordinates
## based on starting location, distance, and bearing
## as.deg indicates if the bearing is in degrees (T) or radians (F)
if(as.deg){
##if bearing is in degrees, convert to radians
bearing=bearing*pi/180
}
newx<-x+dist*sin(bearing) ##X
newy<-y+dist*cos(bearing) ##Y
return(list("x"=newx,"y"=newy))
}
##Example
oldloc=c(0,5)
bearing=200 #degrees
dist=5
newloc<-polar2cart(oldloc[1],oldloc[2],dist,bearing,TRUE)
plot(oldloc[1],oldloc[2],xlim=c(-10,10),ylim=c(-10,10))
points(newloc$x,newloc$y,col="red")
Subscribe to:
Posts (Atom)