Summarizing Circular Data in R: Aspect Angle

Submitted by dylan on Wed, 2012-10-10 15:26.

The orientation of terrain surface (aspect) can have dramatic effects on landscape-scale variation in soil temperature and moisture. Summarizing aspect angle is complicated by the fact that sampled values are measured on a circular scale. The circular package for R can be used to summarize, model, and visualize this type of data.

An example function is presented below that demonstrates several components of the circular package: special data structures, summary functions, plotting functions and their application to circular data derived from measurements collected by compass. Spread and central tendency are depicted with a combination of circular histogram and kernel density estimate. The circular mean, and relative confidence in that mean are depicted with an arrow: longer arrow lengths correspond to greater confidence in the mean.

Circular HistogramCircular Histogram

Code Example

# load library (you may have to install this library first)

# plot a vector of aspect measurements, with units of degrees, measured via compass
aspect.plot <- function(p, p.bins=60,, p.axis=seq(0, 350, by=10), plot.title=NULL) {
        # remove NA
        p <- na.omit(p)
        # make a circular class object: using native degrees, template sets zero and direction
        c.p <- circular(p, units='degrees', template="geographics")
        # compute the mean
        m.p <- mean(c.p)
        # compute mean resultant length
        rho.p <- rho.circular(c.p)
        # setup custom axis
        a.p <- circular(p.axis, units='degrees', template="geographics")
        # circular histogram
        plot(c.p, axes=FALSE, stack=TRUE, bins=p.bins, shrink=1.45, cex=1, sep=0.06, pch=21, col=1, bg='RoyalBlue')
        # add circular density, bw is the smoothness parameter
        lines(density(c.p,, col='RoyalBlue', lty=2)
        # add axes: note work-around for strange bug...
        axis.circular(at=(-a.p) + 90, labels=a.p, cex=0.6)
        # annotate north
        text(0, 1.125, 'North', cex=0.85, font=1)
        # annotate mean with an arrow
        arrows.circular(m.p, shrink=rho.p, length=0.15, col='RoyalBlue')
        # add title
        text(0, -0.25, plot.title, cex=0.85, font=2)

# generate some fake data
p.narrow <- runif(n=25, min=215, max=280)
p.wide <- runif(n=25, min=0, max=270)

# set figure margins to 0, 2-column plot
par(mar=c(0,0,0,0), mfcol=c(1,2))

# plot
aspect.plot(p.narrow,, plot.title='Soil A')
aspect.plot(p.wide,, plot.title='Soil B')


The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <div> <img> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Copy the characters (respecting upper/lower case) from the image.