2

How can I calculate the difference between different rows within different list? and different list have different dimensions. I use the code as follows

names(ri1)
[1] "Sedol" "code"  "ri"    "date"
ri1<-ri1[order(ri1$Sedol,ri1$date),]
sri<-split(ri1,ri1$Sedol)
ri1$r<-as.vector(sapply(seq_along(sri), function(x) diff(c(0, sri[[x]][,3]))))

however it shows the result

"Error in `$<-.data.frame`(`*tmp*`, "r", value = list(c(100, 0.00790000000000646,  : 
replacement has 1485 rows, data has 4687655"

for example

I have three lists

  1. date  ri
    1990  1
    1991  2
    1992  3
    
  2. date  ri
    1990  1
    1991  2
    1992  3
    1993  4
    
  3. date  ri
    1990  1
    1991  2
    

I want the results like

  1. date  ri  r
    1990  1   0%
    1991  2   100%
    1992  3   100%
    
  2. date  ri  r
    1990  1   0%
    1991  2   100%
    1992  3   100%
    1993  4   100%
    
  3. date  ri   r
    1990  1    0%
    1991  2    100%
    

notice: r= r(t+1)/r(t)-1

Taryn
  • 242,637
  • 56
  • 362
  • 405
neojin
  • 11
  • 1
  • 3
  • are you sure about your r formula? it don't give the result – agstudy Jan 01 '13 at 13:43
  • 2
    You could have made your example reproducible by providing `ri1` using `dput`. Please refer to [how-to-make-a-great-r-reproducible-example](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) – flodel Jan 01 '13 at 13:52

2 Answers2

0

You should use a combination of head and tail as follows:

r.fun <- function(ri) c(0, tail(ri, -1) / head(ri, -1) - 1)
lapply(sri1, transform, r = r.fun(ri))

If your goal is to recombine (rbind) your data afterwards, then know that you can split/apply/combine everything within a single call to ave from the base package, or ddply from the plyr package:

transform(ri1, r = ave(ri, Sedol, FUN = r.fun))

or

library(plyr)
ddply(ri1, "Sedol", transform, r = r.fun(ri))

Edit: If you want the output to be in XX% as in your example, replace r.fun with:

r.fun <- function(ri) paste0(round(100 * c(0, tail(ri, -1) / head(ri, -1) - 1)), "%")
flodel
  • 87,577
  • 21
  • 185
  • 223
0

Using diff and lapply you can get something like

# I generate some data
  dat1 <- data.frame(date = seq(1990,1999,length.out=5),ri = seq(1,10,length.out=5))
  dat2 <- data.frame(date = seq(1990,1999,length.out=5),ri=seq(1,5,length.out=5))
# I put the data.frame in a list 
  ll <- list(dat1,dat2)
 # I use lapply:
  ll <- lapply(ll,function(dat){
    # I apply the formula you give in a vector version
    # maybe you need only diff in percent?
    dat$r <- round(c(0,diff(dat$ri))/dat$ri*100)
    dat
  })
ll
[[1]]
     date    ri  r
1 1990.00  1.00  0
2 1992.25  3.25 69
3 1994.50  5.50 41
4 1996.75  7.75 29
5 1999.00 10.00 22

[[2]]
     date ri  r
1 1990.00  1  0
2 1992.25  2 50
3 1994.50  3 33
4 1996.75  4 25
5 1999.00  5 20
agstudy
  • 119,832
  • 17
  • 199
  • 261