vee.burton
vee.burton

Reputation: 53

apply function to subsets of dataframe r

I am trying to subset a dataframe by two variables ('site' and 'year') and apply a function (dismo::biovars) to each subset. Biovars requires monthly inputs (12 values) and outputs 19 variables per year. I'd like to store the outputs for each subset and combine them.

Example data:

data1<-data.frame(Meteostation=c(rep("OBERHOF",12),rep("SOELL",12)),
              Year=c(rep(1:12),rep(1:12)),
              tasmin=runif(24, min=-20, max=5),
              tasmax=runif(24, min=-1, max=30),
              pr=runif(24, min=0, max=300))

The full dataset contains 900 stations and 200 years.

I'm currently attempting a nested loop, which I realised isn't the most efficient, and which I'm struggling to make work - code below:

sitesList <- as.character(unique(data1$Meteostation))
#yearsList<- unique(data1$Year)
bvList<-list()

for (i in c(1:length(unique(sitesList)))) {

   site<-filter(data1, Meteostation==sitesList[i])
   yearsList[i]<-unique(site$Year)

   for (j in c(1:length(yearsList))){

      timestep<-filter(site,Year==yearsList[j])
      tmin<-timestep$tasmin
      tmax<-timestep$tasmax
      pr<-timestep$pr

      bv<-biovars(pr,tmin,tmax)
      bvList[[j]]<- bv

}}

bv_all <- do.call(rbind, bvList)

I'm aware there are much better ways to go about this, and have been looking to variations of apply, and dplyr solutions, but am struggling to get my head around it. Any advice much appreciated.

Upvotes: 1

Views: 183

Answers (2)

user2474226
user2474226

Reputation: 1502

You could use the dplyr package, as follows perhaps?

library(dplyr)
data1 %>% 
    group_by(Meteostation, Year) %>%
    do(data.frame(biovars(.$pr, .$tasmin, .$tasmax)))

Upvotes: 2

jay.sf
jay.sf

Reputation: 72828

Use by and rbind the result.

library("dismo")
res <- do.call(rbind, by(data1, data1[c("Year", "Meteostation")], function(x) {
  cbind(x[c("Year", "Meteostation")], biovars(x$pr, x$tasmin, x$tasmax))
}))

Produces

head(res[, 1:10])
#   Meteostation Year      bio1     bio2 bio3 bio4       bio5       bio6     bio7 bio8
# 1      OBERHOF    1 12.932403 18.59525  100   NA 22.2300284   3.634777 18.59525   NA
# 2      OBERHOF    2  5.620587  7.66064  100   NA  9.4509069   1.790267  7.66064   NA
# 3      OBERHOF    3  0.245540 12.88662  100   NA  6.6888506  -6.197771 12.88662   NA
# 4      OBERHOF    4  5.680438 45.33159  100   NA 28.3462326 -16.985357 45.33159   NA
# 5      OBERHOF    5 -6.971906 16.83037  100   NA  1.4432801 -15.387092 16.83037   NA
# 6      OBERHOF    6 -7.915709 14.63323  100   NA -0.5990945 -15.232324 14.63323   NA

Upvotes: 1

Related Questions