0

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)

4
  • but your loop doesn't produce what you want it returns, Error: object 'wk.seas' not found. Commented Oct 7, 2015 at 18:59
  • @user sorry, I didn't copy everything I needed to- it should work now Commented Oct 7, 2015 at 19:11
  • do you have a code as to what each of the seasons constitute? Eg, what numbers do "win" cover etc etc, if so you could take that approach. Commented Oct 7, 2015 at 19:21
  • @CDVAK why do you want to use lapply? Commented Oct 7, 2015 at 19:24

2 Answers 2

4

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)
Sign up to request clarification or add additional context in comments.

Comments

1

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.

2 Comments

I used five lines of the "2. Base commands" code to add the seasons instead of trying to write a function to do it in one step. Thanks,
Just to circle back on this-merge as below is the correct approach if you have the list of seasons and their criteria listed out. I posted this reply to a later-edited version of your question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.