CDVAK
CDVAK

Reputation: 13

Using lapply instead of for loop in r

I am having trouble writing a function to replace a for() loop in R.

My data looks like this:

dat1<-rep(sprintf("%02d", 0:52),10)
dat1<-as.data.frame(dat1[40:length(dat1)])
colnames(dat1)<-c("wk")
wk.seas<-c(rep("win",9),rep("spr",13),rep("sum",13),rep("aut",13),rep("win",6))
wks<-sprintf("%02d", 0:53)

This loop produces what I want:

for(j in seq_along(dat1[,1])){
    dat1$season[dat1[,1]==wks[j]]<-wk.seas[j]
}#works

I am looking to create a vector in the df with a value for season that corresponds to the week of the year.

Here is my attempt to replicate this loop with a function/lapply combo:

lapply(seq_along(dat1$wk), function(d){
    dat1$season[dat1$wk==wks[d]]<-wk.seas[d]
}) #not working

Thank you (edited to add missing code)

Upvotes: 0

Views: 887

Answers (2)

Andrew Cheesman
Andrew Cheesman

Reputation: 150

There are probably a bunch of ways to solve the problem, but two quick solutions come to mind:

  1. Ifelse:

dat1$seas <- ifelse(dat1$wk>=15 & dat1$wk<41, "summer", NA)

  1. Base commands:

dat1[dat1$wk>=15 & dat1$wk<45,2] <- "summer"

You'd want one for each season that you want to designate.

Also, upon creation dat1$wk is being formatted as a factor; I had to pass dat1$wk <- as.numeric(dat1$wk) in order to be able to do either of the above.

EDIT: +1 for merge/join, if you have the season table elsewhere.

Upvotes: 1

Matthew Lundberg
Matthew Lundberg

Reputation: 42689

lapply is the wrong approach. The reason that the lapply code above doesn't work is because you're modifying an object within a function, which modifies a local copy in the function's environment. Any of the apply functions will capture the return value and aggregate that; you should not rely on function side-effects.

You're really performing a merge here. Use merge:

wk <- data.frame(wk=wks, season=wk.seas)
merge(wk, dat1)

Upvotes: 4

Related Questions