Tuesday, January 26, 2016

Repeatability, intraclass correlation coefficient, and measurement error in R and SAS

Measurement error is "the variability of repeated measurements [...] relative to its variability among individuals in a particular group" (Bailey and Byrnes 1990, pg 124).  In other words, how  much wobble is there in repeated samples on the same individual?  I used measurement error in Curry and Patten (2014) after learning about the idea in a graduate multivariate statistics class I took a few years ago.  Papers such as Lougheed et al. (1991) and Marantz and Patten (2010) showed implementations.  I am now wanting to implement the same idea for repeated songs by the same individual bird in a species that sings one song type per individual.  How much does a bird vary in repeats of its standardized song?

I first started looking for how to implement a model II nested random effects ANOVA (as described in Bailey and Byrnes 1990), like SAS's PROC NESTED but in R, and ran into the usual problems trying to get the two programs to give equivalent output (where were my mean squares in R?  So aggravating sometimes...).  I was also looking to see exactly how a similar concept that I just learned about, repeatability (Lessells and Boag 1987; also known as the intraclass correlation coefficient), was related.  At first I thought they were the same thing, but after carefully writing out the equations from both Bailey and Byrnes (1990) and Lessells and Boag (1987), I realized they can be calculated easily from one another (and I was backed up by further reading in Wolak et al. 2012, pg. 130, who state "measurement error is simply one minus the repeatability", as I had suspected).   Measurement error uses within-groups mean square error (or variance within groups) as the numerator in the calculation, while the intraclass correlation coefficient (or repeatability) uses the among-group variance (which both Lessells and Boag 1987 and Bailey and Byrnes 1990 show to calculate using the same method).

As an aside, repeatability appears to be used rather broadly, and intraclass correlation coefficient also appears to have some other defintions, if wikipedia's summary is to be believed, but in the papers I am citing they all are comparing within and among group variation (the ANOVA framework).

Armed with this new terminology and knowledge, I decided to use the R package 'ICC' (Wolak et al. 2012) which calculates repeatability.  I tested this on some sample data from the SAS website with both the model II nested ANOVA as used in Bailey and Byrnes (1990) and in R.

Use the "turnip" dataset as the SAS website shows, then run this modified code:

   proc nested data=turnip;
      classes plant;
      var calcium;
   run;

To get this:























Calculate repeatability with these highlighted numbers using is the equation from Lessells and Boag (1987); 6 is the number of samples per individual, i.e. the number of repeated measurements:
((2.520115-0.135502)/6)/(0.135502+((2.520115-0.135502)/6))
Repeatability=0.745745

To calculate measurement error, substitute 0.135502 for the current numerator (i.e. use the Bailey and Byrnes 1990 equation).
0.135502/(0.135502+((2.520115-0.135502)/6))
Measurement error=0.254255

Adding the two numbers together gets 1, which means all the variation is accounted for (and thus you only need to calculate one; to get the other just subtract from 1).

Using the ICC package's function ICCest() gives essentially the same answer (the difference appears to be the level of precision in the decimal places), but also provides confidence intervals and other data that are explained more in the Wolak et al. paper.  (Import the data first, obviously, before running this code.  You can enter it by hand or export from SAS as a .csv).

ICCest(x=plant, y=calcium, data=turnip)

>$ICC
>[1] 0.7457443
>
>$LowerCI
>[1] 0.3889918
>
>$UpperCI
>[1] 0.9776527
>
>$N
>[1] 4
>
>$k
>[1] 6
>
>$varw
>[1] 0.1355025
>
>$vara
>[1] 0.3974355

The highlighted number is repeatability, which is essentially the same as the calculation by hand from SAS barring what I believe are differences in decimal precision used in the numbers for calculating the answer.

Finally, since SAS uses a random effects model, I hoped that one might be able to calculate measurement error by hand from R just to be sure it all works.  I found a page comparing different methods of repeatability in R that showed an example using the package 'lme4'.  Calcium is the measured variable, plant is the random effect, and there are no fixed effects.

model.repeat<-lmer(calcium~1+(1|plant),
               data=turnip)
summary(model.repeat)

>results>Linear mixed model fit by REML t-tests use Satterthwaite >approximations to degrees
>  of freedom [lmerMod]
>Formula: calcium ~ 1 + (1 | plant)
>   Data: turnip
>
>REML criterion at convergence: 31.2
>
>Scaled residuals: 
>     Min       1Q   Median       3Q      Max 
>-1.09999 -0.85753 -0.09009  0.69564  2.13276 
>
>Random effects:
> Groups   Name        Variance Std.Dev.
> plant    (Intercept) 0.3974   0.6304  
> Residual             0.1355   0.3681  
>Number of obs: 24, groups:  Plant, 4
>
>Fixed effects:
>            Estimate Std. Error    df t value Pr(>|t|)   
>(Intercept)    3.012      0.324 3.000   9.295  0.00264 **
>---
>Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Use the residual (error, or within) as the numerator if you want to calculate measurement error, or the plant (among groups) variance as the numerator if you want to calculate repeatability.  For example, for measurement error, you get pretty close to the SAS-by-hand number.
0.1355/(0.3974+0.1355)
Measurement error=0.2542691

So, all three methods (by hand with lme4 in R, using the ICC package in R, and by hand from SAS PROC NESTED) give comparable results for the balanced design (for the plant dataset, n=6 for every individual plant, i.e. there are six measurements for any given plant).  For an unbalanced design, with varying numbers of measurements per group, Lessells and Boag (1987) provide an equation to calculate the appropriate sample size coefficient n0 (see their equation 5).  The ICC package uses that equation to calculate n0 (Wolak et al. 2012; this is listed as $k in the output from ICCest)  I tested this in the R packages only as I was hoping the variance from lme4 might have already been adjusted for the sample size coefficient issue.  ICC already states that they adjust (Wolak et al. 2012 and in the help file).  With the first row deleted from the turnip data set, ICC gives a repeatability value of 0.7432083 and k (which is n0 from Lessells and Boag)= 5.73913 (slightly under the previous 6, which makes sense as I deleted one row).  With that same one-row-deleted data using lme4, I took the random effects variances (0.3952/(0.1419+0.3952)) and got 0.7358034, so its variance calculation is not including the repeatability adjustment for n0.  This is not really surprising since that's not what it's designed to do.

So, what I will be doing to check for "measurement error" on my birds (how much "wobble" each bird has in its otherwise standard songs) is substitute the song variable (let's say frequency) for "calcium" and the bird ID (individual ID or band number) for "plant".  The random effect in lmer, the classes in SAS PROC NESTED, and x in ICCest are all the individual/subject/item from which you get repeated measurements for measurement error or repeatability.

Take home message: ICC is the easiest to use as it will take into account an unbalanced design for you already.  With SAS you can calculate for an unbalanced design but you'll have to do it by hand.  Thus, ICC and SAS should cover all cases.  With lme4 you can calculate repeatability and measurement error for balanced designs by hand, but I don't see a particularly obvious way to get the mean squares as in SAS (and I need to move on to other parts for the analysis), so I'm going to leave it at that for now.

Here are the papers I used to understand how to calculate measurement error and repeatability:
Bailey RC, Byrnes J. 1990. A new, old method for assessing measurement error in both univariate and multivariate morphometric studies. Systematic Biology 39:124–130.
Lessells CM, Boag PT. 1987. Unrepeatable repeatabilities: a common mistake. Auk 104:116–121.
Wolak ME, Fairbairn DJ, Paulsen YR. 2012. Guidelines for estimating repeatability.  Methods in Ecology and Evolution 3:129-137.

and here are some helpful examples of papers that use measurement error:
Lougheed SC, Arnold TW, Bailey RC. 1991. Measurement error of external and skeletal variables in birds and its effect on principal components. Auk 108:432–436.
Marantz CA, Patten MA. 2010. Quantifying subspecies analysis: a case study of morphometric variation and subspecies in the woodcreeper genus Dendrocolaptes. Ornithological Monographs 67:123–140.

Tuesday, January 19, 2016

A belated Happy New Year from the frozen north

May all the snow you eat be tasty and fresh.  10 January 2016, Winnipeg, MB, Canada.

Tuesday, December 08, 2015

North Central Texas Wildflowers: a field guide

I am very delighted to announce that my mom, Mary Curry, has published a field guide to the wildflowers of north central Texas, featuring her superb photos for a huge number of wildflowers in the region!  She has taken beautiful photos that show key identifying features of each species, with both whole-plant views and close-ups of flowers, leaves, and stems (and multiple photos for almost every species).  The whole book is cross-referenced with the Flora of North-Central Texas, as well, for an easy route to additional information.  Her book is available on amazon; I highly recommend it!

Tuesday, November 24, 2015

"Winter is here"

So declared one of the Environment Canada weather bulletins last Thursday morning.  And several days before that, a hilarious "Winter is coming" preceded their more detailed forecast.  Sure enough, we had several centimeters/an inch or two of snow!
Snow, with dog for scale.  I first saw that phrase in an older paper about... sparrows?  grasslands?  I wish I could remember what paper it was, but it appears to be a not-uncommon unit of measurement, as a google search found several other people using this helpful scale.  19 November 2015, Winnipeg, Manitoba, Canada.

Tuesday, November 17, 2015

Error bars on points in R

Putting error bars on figures is surprisingly complicated sometimes (even in Excel...).  I have to google it every time for R.  Various packages can do it, but base R also has some functions that will help (segments and arrows).  I like arrows() because you don't have to draw extra bits to get the nice line on the end of your error bars, which it seems you need to do if you use segments().

#Plot your center points; you could use your averages or other value here.
#Play around with the values in x and y to see what numbers move which part.
plot(x=c(1,2),
     y=c(2,3),
     xlim=c(0,3),
     ylim=c(0,5),
     xlab="x",
     ylab="y",
     pch=21, bg="black")

#Here are error bars on the left point at (1,2).
arrows(x0=c(1,1),
       y0=c(2,2),
       x1=c(1,1),
       y1=c(1,3),
       length=0.25,
       angle=90)

#you can draw each error bar one at a time to get a better idea of how the code works.
#I show these in blue so you can see as it draws over the original bar on the plot.
arrows(x0=c(1),
       y0=c(2),
       x1=c(1),
       y1=c(1),
       length=0.25,
       angle=90,
       col="blue")

#top error bar.
arrows(x0=c(1),
       y0=c(2),
       x1=c(1),
       y1=c(3),
       length=0.25,
       angle=90,
       col="blue")

#Then let's re-do the plot and draw error bars for both points at the same time.
plot(x=c(1,2),
     y=c(2,3),
     xlim=c(0,3),
     ylim=c(0,5),
     xlab="x",
     ylab="y",
     pch=21, bg="black")

arrows(x0=c(1,1,2,2),
       y0=c(2,2,3,3),
       x1=c(1,1,2,2),
       y1=c(1,3,2,4),
       length=0.25,
       angle=90)

#You can see you end up with a list of points,
#so you can set these values from other calculations you make of
#standard deviation, standard error, confidence intervals,
#or whatever you are using.

Tuesday, November 10, 2015

Sorting, grouping, and selecting data in R

I got started sorting data in SQL.  Nice select functions where some variable equals some value and you can get distinct or unique values.  R confused me. I was delighted to find an R package that allows the use of SQL selects in R, but it can occasionally be a bit clumsy due to differences in table and object naming.  I kept seeing references to dplyr as the modern way to use R natively to organize my data.  So, I have decided it is time to start learning dplyr and already it is helping a ton.  I recommend starting with the dplyr vignette.  I also found this tutorial with different sample data to be helpful.  I tried out chaining (the mysterious %>% operator I have seen lurking in code occasionally) and it was fantastic.  No more weird intermediate variables!  The tutorial describes a different-package-specific version of chaining, but dplyr implements it as well (the help file says it was formerly '%.%' but the '%>%' version has become standard) so it worked fine even though I hadn't installed the other 'magrittr' package mentioned on that page.  So far the biggest help to me is the distinct() function, which gets unique combinations of factors as I get when I do simpler and simpler SQL selects (instead of getting repeated rows of categorical data when I try to subset using base R for some variable that does have additional unique variables that I am not currently interested in).

Tuesday, November 03, 2015

Installing libraries on a linux operating system

Now that my computer can dual-boot into Ubuntu and Windows, I am going to start getting things set up for my original need for a Linux-type operating system: a program for estimation of genomic clines called bgc.  Installing the GNU Scientific Library was first.  I searched for it in the software center, and I was surprised to have 15+ options in the search results.  I eventually chose "GNU Scientific Library (GSL) -- library package".  It noted in "more info" that "To compile your own programs you also need to install libgsl0-dev", which I figure I do since bgc requires compiling.  I installed that one too.  Easy enough!

HDF5 at first seemed like it would be similarly easy, but all the binaries ready for installing were for either Windows or CentOS Linux, which I assume would be different.  So I have to compile it.  I followed "Compiling the easy way" from the Ubuntu website.

Step 1.  I wasn't sure if I was supposed to remove the $ before $USER.  Turns out I was.  I got an error when I tried $claire for my user name.  "chown: missing operand after ‘/usr/local/src’"  It worked fine when I just put claire though.  The hdf5 instructions say I need 'gcc' to compile it.  This Ubuntu help says build-essential contains gcc, and the "Compiling the easy way" did have me install it in this step.

Step 2. Obtain the package!  I got a .tar with Unix line endings (since the other options were Mac or Windows line endings) and .tar.gz seemed more complicated.  I moved it to the /user/local/src folder (which is under "Home") and right-clicked, then "Extract here".  I looked in the folder and there seemed to be some configure files, so I'll go ahead and try the next step

Step 3. The link to auto-apt confused me, so i went with the manual version, installing apt-file and its update ("sudo apt-get install apt-file" then "sudo apt-file update" which did not take as long as the instructions threatened on my reasonably fast connection, maybe five minutes at most).  I went into my directory (/usr/local/src) in the terminal as instructed, and ran ./configure and it gave me a different error message.  I navigated one level lower (to /usr/local/src/hdf5-1.8.15-patch1) and then it worked!  It did not end with any dependency errors, but it also did not obviously with config.status: creating Makefile.  I scrolled back up and found it, though, along with lots of other creating of filenames in various directories, and "no obvious errors" as the Ubuntu page said, so on to Step 4.

Step 4. It says to give the command "make".  I did.  Many things began happening, including warnings about overflows and floating points and such.  However, it kept going, so I let it be.  The hdf5 instructions said to "make install" in their step 4.3.1 so hopefully that didn't mess it up.  It took maybe five minutes.  As I read the Ubuntu instructions further "sudo checkinstall" replaces "make install".  I did the sudo checkinstall and the terminal asked if i wanted to create a default set of package docs.  Only one option ("y") so I said yes.  Then it wanted me to write a description for the package and end it with an empty line or EOF.  I wrote hdf5 and then pressed enter.  But enter just gave me a new line prefixed with >>.  So, end of file (EOF) is ctrl+D in linux?  But a blank line might work too?  I tried the blank line first.  That worked (pressing enter twice to create the blank line).  Next up it gave me a list of values for building the package (maintainer, summary, name, version, etc).  I couldn't think of any changes so I pressed enter to continue.  Then I messed up and tried to copy the message and ctrl+c did something, not sure what.  So I ran "sudo checkinstall" again and it seemed happy to return to the same message.  I pressed "y" when it asked me this:

Some of the files created by the installation are inside the build
directory: /usr/local/src/hdf5-1.8.15-patch1

You probably don't want them to be included in the package,
especially if they are inside your home directory.
Do you want me to list them?  [n]: y

This got me to a weird screen with (END) at the bottom.  Help me, google!  Pressing Q and then enter got me back to the main screen where it asked:

Should I exclude them from the package? (Saying yes is a good idea)  [y]: y

The install failed.

dpkg-deb: error: parsing file '/var/tmp/tmp.d7tq23dvxW/package/DEBIAN/control' near line 7 package 'hdf5-1.8.15':
 error in 'Version' field string 'patch1-1': version number does not start with digit

So I tried again.

I keep forgetting and pressing ctrl+c.
*** SIGINT received ***

Restoring overwritten files from backup...OK

Cleaning up...OK

Bye.

According to wikipedia, if I understand correctly, this just interrupts the current process.  So, it should be okay.

Anyway, the new install with version number changed to 1.8.15-patch1 installed fine!

******************************************************************
 Done. The new package has been installed and saved to

 /usr/local/src/hdf5-1.8.15-patch1/hdf5-1.8.15_1.8.15-patch1-1_amd64.deb

 You can remove it from your system anytime using:

      dpkg -r hdf5-1.8.15
*******************************************************************

I'm still not really sure if that's where I wanted it installed, but this stackexchange answer seems to indicate it is an appropriate place and I think section 4.6 in the hdf5 instructions agrees.

Step 4.5 in the hdf5 instructions suggests testing the library, so I ran "make check" and waited for it to go through its paces, which took about three minutes.  It didn't return any errors so I appear to have installed it!   Soon I will compile bgc and see if that works; presumably if the hdf5 install didn't go right in non-obvious way, I will find out then.