Andrew
Andrew

Reputation: 546

Referencing previous rows of a data.frame to compute a new column in R

I am trying to calculate changes in weight between visits to chicks at different nests. This requires R to look up the nest code in the current row, find the previous time that nest was visited, and subtract the weight at the previous visit from the current visit. For the first visit to each nest, I would like to output the current weight (i.e. as though the weight at the previous, non-existent visit was zero).

My data is of the form:

Nest   <- c(a,b,c,d,e,c,b,c)
Weight <- c(2,4,3,3,2,6,8,10)
df <- data.frame(Nest, Weight)

So the desired output here would be:

Change <- c(2,4,3,3,2,3,4,4)

I have achieved the desired output once, by subsetting to a single nest and using a for loop:

tmp <- subset(df, Nest == "a")
tmp$change <- tmp$Weight
for(x in 2:(length(tmp$Nest))){
tmp$change[x] <- tmp$Weight[(x)] - tmp$Weight[(x-1)]
}

but when I try to fit this into ddply

df2 <- ddply(df, "Nest", function(f) {
  f$change <- f$Weight
  for(x in 2:(length(f$Nest))){
    f$change <- f$Weight[(x)] - f$Weight[(x-1)]
  }
})

the output gives a blank data.frame (0 obs. of 0 variables).

Am I approaching this the right way but getting the code wrong? Or is there a better way to do it?

Thanks in advance!

Upvotes: 2

Views: 2614

Answers (2)

jlhoward
jlhoward

Reputation: 59345

Here is a data.table solution. With large data sets, this is likely to be faster.

library(data.table)
setDT(df)[,Change:=c(Weight[1],diff(Weight)),by=Nest]
df
#    Nest Weight Change
# 1:    a      2      2
# 2:    b      4      4
# 3:    c      3      3
# 4:    d      3      3
# 5:    e      2      2
# 6:    c      6      3
# 7:    b      8      4
# 8:    c     10      4

Upvotes: 1

G. Grothendieck
G. Grothendieck

Reputation: 269481

Try this:

library(dplyr)
df %>% group_by(Nest) %>% mutate(Change = c(Weight[1], diff(Weight)))

or with just the base of R

transform(df, Change = ave(Weight, Nest, FUN = function(x) c(x[1], diff(x))))

Upvotes: 4

Related Questions