Finding year of first occurrence in R

Viewed 286

I have a dataset in R containing data collections from similar sites over multiple years. I am looking to find the first year for each site in which a value of 1 has occurred. Values of 1 are not guaranteed to occur. My dataset looks like the following:

Site   Year   Value
"asdf" 2017   0
"zxcv" 2008   1
"wefd" 2012   0
"asdf" 2015   1
"asdf" 2019   1
"wefd" 2013   0

I attempted to use a for loop to subset each year's values, and then merge to list all sites side by side but could not get it to work.

3 Answers

After grouping by 'Site', get the index of first row where Value is 1 and slice that row

library(dplyr)
df1 %>%
   group_by(Site) %>%
   slice(match(1, Value))

It may also be safer to ensure that the 'Year' returned is the earliest in case the records are not ordered by that column, i.e.

df1 %>%
    group_by(Site) %>%
    arrange(Site, Year) %>%
    slice(match(1, Value))

In basic R you could do this with a simple aggregate:

minYear = aggregate(year ~ site, data = df[df$value==1, ], FUN = min)

This will return the lowest year for each site and, since the data is df with only those rows that have 1 at the value column. And this works even if the years are not in order.

Example:

df = data.frame(site = c("one", "two", "three"), 
                year = c(2000, 1999, 2010, 1987, 1991, 2004, 2020, 2009, 1992),
                value = c(1,1,0,1,0,1,1,0,0))

> df
   site year value
1   one 2000     1
2   two 1999     1
3 three 2010     0
4   one 1987     1
5   two 1991     0
6 three 2004     1
7   one 2020     1
8   two 2009     0
9 three 1992     0

Result:

minYear = aggregate(year ~ site, data = df[df$value==1, ], FUN = min)

> minYear
   site year
1   one 1987
2 three 2004
3   two 1999

If there is no row filtering by value then you get:

minYear_no_filter = aggregate(year ~ site, data = df, FUN = min)

> minYear_no_filter
   site year
1   one 1987
2 three 1992
3   two 1991

First occurrence:

If you want the first occurrence (the year for each site where the value was 1) then do:

firstYear = aggregate(year ~ site, data = df[df$value==1, ], FUN = head, 1)

> firstYear
   site year
1   one 2000
2 three 2004
3   two 1999

You could also use data.table package as follows:

library(data.table)
setDT(df)[Value == 1, .SD[order(Year)][1], Site]

#      Site  Year Value
# 1:   zxcv  2008     1
# 2:   asdf  2015     1
Related