Thursday, July 10, 2014

Stratified random sampling in R using dplyr

A recent Gist I wrote

Setup

Let’s say I have a number of sample units for which I have observed some characteristic(s) at two time-points. In my specific case, I have species abundance data for 120 plots in 1992 and 2011. Using these data, I calculated the species turn-over between the two time points for each plot. I then shuffled the 2011 plots, leading to random pairing of plots between the two time points, and recalculated the turn-over.
There are many cases in which we may want to do something similar to this, and many non-parametric randomization methods use a similar setup. The particular problem I faced is that the plots were stratified into broad vegetation types, Fynbos, Thicket, and Grassland. When shuffling the 2011 plots, I wanted to shuffle plots only within their vegetation type. I thought up of a number of complicated ways to write a function to do this, and even started coding one up. Then I thought about how I could use dplyr to carry out stratified random sampling. Here’s an example of how it works.

Make a data set

Here is a sample data set including 20 plots (p1, …, p20), randomly assigned into one of three categories. I’ve printed out the data set, since it’s small.
## Load dplyr
require( dplyr )
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## 
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## 
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
## Make data.frame
df <- data.frame( plot = paste( "p", 1:20, sep = "" ),
                  category = sample( x = letters[1:3], size = 20, replace = TRUE ),
                  stringsAsFactors = FALSE )

## Print data.frame, arranged by category
print( arrange( df, category ) )
##    plot category
## 1    p3        a
## 2    p8        a
## 3   p12        a
## 4    p1        b
## 5    p2        b
## 6    p4        b
## 7    p5        b
## 8    p9        b
## 9   p15        b
## 10  p17        b
## 11  p19        b
## 12  p20        b
## 13   p6        c
## 14   p7        c
## 15  p10        c
## 16  p11        c
## 17  p13        c
## 18  p14        c
## 19  p16        c
## 20  p18        c

Simple shuffle

Shuffling plots, disregarding their category classification, is easy - just use sample. Below I’ve printed out the shuffled paired-plots.
## Shuffle plots
plots_shuffled <- sample( df$plot )

## Print plots and plots_shuffled together
print( cbind( df$plot, plots_shuffled ) )
##             plots_shuffled
##  [1,] "p1"  "p5"          
##  [2,] "p2"  "p13"         
##  [3,] "p3"  "p16"         
##  [4,] "p4"  "p14"         
##  [5,] "p5"  "p1"          
##  [6,] "p6"  "p3"          
##  [7,] "p7"  "p20"         
##  [8,] "p8"  "p2"          
##  [9,] "p9"  "p11"         
## [10,] "p10" "p19"         
## [11,] "p11" "p10"         
## [12,] "p12" "p17"         
## [13,] "p13" "p9"          
## [14,] "p14" "p7"          
## [15,] "p15" "p6"          
## [16,] "p16" "p8"          
## [17,] "p17" "p15"         
## [18,] "p18" "p4"          
## [19,] "p19" "p12"         
## [20,] "p20" "p18"

Stratified random sampling (shuffling)

But what if we want to account for the category classification? Here’s how I used dplyr to perform stratified random sampling.
## Use dplyr group_by and mutate to randomly sample within category
df <- 
  group_by( df, category ) %.%
  mutate( strat_rsamp = sample( plot ) )

print( arrange( df, category ) )
## Source: local data frame [20 x 3]
## Groups: category
## 
##    plot category strat_rsamp
## 1    p3        a         p12
## 2    p8        a          p3
## 3   p12        a          p8
## 4    p1        b          p5
## 5    p2        b         p20
## 6    p4        b          p9
## 7    p5        b         p15
## 8    p9        b         p17
## 9   p15        b          p1
## 10  p17        b          p2
## 11  p19        b          p4
## 12  p20        b         p19
## 13   p6        c         p11
## 14   p7        c         p14
## 15  p10        c          p7
## 16  p11        c         p10
## 17  p13        c         p16
## 18  p14        c         p18
## 19  p16        c         p13
## 20  p18        c          p6
We could also return just a vector of the shuffled samples, without the data.frame. Convenient, but not very pretty code-wise
( group_by( df, category ) %.%
    mutate( strat_rsamp = sample( plot ) ) )$strat_rsamp
##  [1] "p5"  "p20" "p8"  "p9"  "p15" "p16" "p11" "p3"  "p19" "p18" "p14"
## [12] "p12" "p13" "p10" "p4"  "p6"  "p1"  "p7"  "p17" "p2"

Conclusion

There you have it - stratified random sampling. There may be an even easier way to do this (perhaps I missed a function or didn’t dive into sample enough?), but this seems pretty easy to me. Thanks dplyr!

Saturday, June 21, 2014

Difficulties of opportunistic field data

It seems that every time I work with field data, both data I collected and data I have been given to analyze, I come across a few common problems. There are usually transcription errors to deal with, which can be easy to handle when I have access to the original data sheets. There are outliers to detect, some sleuthing to be done to determine if "this tree really is 40 meters tall? or 4 meters tall?" And other similar problems, mostly due to little mistakes made here and there. But a problem I've been thinking about recently is how to deal with opportunistic field data.

Since, as far as I know, I just made this term up, let me describe what I mean. Opportunistic data are data collected piecemeal while collecting the data you have planned to collect. Or, they are data that "add information" but are not consistently collected at every site you visit. For example, when I ran my first transects to collect size and reproductive trait data for Glossy buckthorn I noticed that many plants appeared to have been browsed. Based on my reading prior to my field work, I was confident that buckthorn wasn't browsed by the native fauna, so I wasn't planning on collecting this type of information. However, I thought "hey, I should make a record when a plant looks like it's been chewed on". But I didn't make it uniform, I didn't add it to the data sheet as another column (the data sheets were already printed out and didn't have space for an extra column!). I just committed to commenting on it in the "Notes" column. At some point I also started noting whether a plant was damaged or not, also in the "Notes" column. By the time I got to transcribing the data into CSV files, I really couldn't distinguish damage, from browsing, from failure to make a note of either. I was left with data for some plants, and not really knowing if plants that weren't noted were free from damage/ browsing, or unobserved for damage/browsing.

Perhaps the biggest problem I had is that if I started recording a piece of information in the way I described above, I wasn't really as dedicated to it as I was to the data I originally set out to collect. As another example, I have photos of some of my seedling plots, but not the ones that I thought, "oh, there aren't that many here. I'll note the number and that will be fine". This might seem like an action taken out of laziness, but really I think data collection involves constant triage. "I need to measure X number of plants. This extra information is not as important as achieving that goal." In the end, I collected plenty of incomplete data during my field work, mostly as observations jotted down as notes, which never saw any type of formal analysis. However, these notes were important to return to when I was thinking about my system while sitting in my office. "Oh that's right, there was a breakout of oat crown rust in some of those areas that seemed to affect fruit counts on some of my plants. Disease may play a role in the population dynamics of this system." Now I'm working with data sets collected by others, that include similar incomplete pieces of information. As someone new to the system, I'm gaining insight from some of this information, but it's hard not to look at some of it and think "if we only had quantitative measures of soil depth for the full data set, we'd be able to say so much more!"

I'm sure I'll continue to collect opportunistic data in the future. If I didn't I wouldn't really be doing my job of observing patterns in nature. Also, I'd like to delve deeper into analysis methods that can be used with these data. Based on conversations I've had with colleagues in the past, I know that we need not simply shelve data because it's not consistent. But ultimately, I do hope that the next time I'm in the field collecting and something interesting comes up, I'll think, "I should take care in collecting that information, I'm going to want that information!"

Thursday, April 10, 2014

Completing my PhD (whilst working as a Post Doc)

Just over a week ago I defended my PhD. Almost 10 months ago I started my Post Doc. This shuffling of the order in which one "should" progress is not uncommon. I know at least a few other people who started their post doc, then went back to their PhD institution to defend. About four weeks ago, as I was finishing up my dissertation to send it off to my committee, I would say that I wasn't sure it was a good idea to take a post doc before you finish. The past 10 months have certainly been challenging. Going into it, I figured that I could probably work between 60 and 80 hours a week. After all, there are so many hours in the day. Start my post doc work at 7 AM, finish up around 4 PM, that still leaves me 6 to 7 hours of work time before I need to go to sleep. I quickly realized that was pretty naive. Perhaps some can work that hard for extended periods of time, but likely not many (as this post at Dynamic Ecology suggests http://bit.ly/1kD6KzG). This meant that it took me longer to complete my dissertation than I initially anticipated. But now, looking through the rose tinted glasses that come with a successful defense, it's easy to think, "oh yes, this was definitely a good idea". So, I thought I might list a few pros and cons, based on my experience.

Pros:
* My post doc is in a lab I had been following for some time, focusing on research that is incredibly interesting to me, with excellent colleagues - hard to beat that.
* I work close enough to home, in a flexible enough environment, to partially solve the two body problem. (My wife has a faculty position at a medical school on Long Island. We don't want to live separately and I would never ask her to leave her position so I can take a three year temporary position.)
* I am going to get to go to the Cape Floristic Region of South Africa! How cool is that?
* Working on my post doc gave me a wider view of the field of plant ecology, which helped me frame my PhD work as I was finishing up. In general, there was a great deal of reciprocal transfer of knowledge (in my own head) between my post doc project and my PhD work.

Cons:
* No free time, or almost none. I turned down a lot of invitations from family and friends over the past ten months, and always felt guilty when I didn't.
* As I said above, the time to completion for my PhD was extended. This was perhaps the greatest challenge.
* Hours wise, I'm pretty confident that I was fulfilling my post doc obligations, but I wasn't as efficient or as productive as I wanted to be. In part I think this was because my intellectual energy was split,
* I did not publish my chapters as I completed them, leaving me with three unpublished dissertation chapters (but perhaps it will be nice to have manuscripts almost ready to submit over the next year.)

Where to now? I'm excited to devote most of my energy to my post doc work (I have to reserve some to wrap up side projects that I let languish), and I'm optimistic about what I can accomplish in the next year and a half. I wouldn't be in this position if I had waited until I was finished to take a post doc. With that said, I have every intention on giving my future students a realistic portrayal of what this decision can feel like. And given the number of finishing PhD students who start their post docs early, I assume they too will do what they think is best for them at that time, just like I did.