简体   繁体   中英

How to shift a column by one row for each new ID in R

Here is my data table called "stock":

TickerID      Date    Open    Close 
    A     1/1/2013    42.1     43.4
    A     1/2/2013    43.4     42.3
    A     1/3/2013    42.3     44.1
   AA     1/1/2013    28.7     28.9
   AA     1/2/2013    28.9     28.4
   AA     1/3/2013    28.4     29.1
  AAA     1/1/2013    61.1     62.1
  AAA     1/2/2013    62.1     63.5
  AAA     1/3/2013    63.5     64.4

How can I add columns that allows each TickerID to present tomorrows open & close value? I also need to have an NA when the TickerID does not have a "next date" I would like for it to look like this:

TickerID      Date    Open    Close  OpenTom  CloseTom
    A     1/1/2013    42.1     43.4     43.4      42.3
    A     1/2/2013    43.4     42.3     42.3      44.1
    A     1/3/2013    42.3     44.1       NA        NA
   AA     1/1/2013    28.7     28.9     28.9      28.9
   AA     1/2/2013    28.9     28.4     28.4      29.1
   AA     1/3/2013    28.4     29.1       NA        NA
  AAA     1/1/2013    61.1     62.1     62.1      63.5
  AAA     1/2/2013    62.1     63.5     63.5      64.4
  AAA     1/3/2013    63.5     64.4       NA        NA

Here is the code I am trying:

for (i in 2:nrow(stock)){
    if(stock[i,"TickerID"]==NYSE[i-1,"TickerID"]){
         stock[i,"CloseTom"] <- stock[i+1,"Close"]
         stock[i,"OpenTom"] <- stock[i+1,"Open"]
     }
}

How can I speed this code up so I can use it on 300,000+ rows?

Note: I do not need to check to see if the next row has the next date, I know this to be true

Try the following. OpenTom and CloseTom are basicly the same columns as Open and Close. Close simply has a lag of 1 and they have some missing values so:

Stock$OpenTom <- Stock$Close
Stock$CloseTom <- c(Stock$Close[2:length(Stock$Close)],NA)

Then find the last occuring value of TickerID. !duplicated() find the first unique element, so you can apply this to the reverse of the column and reverse it back again.

lastday <- rev(!duplicated(rev(Stock$TickerID)))

Then simply replace these IDs with NA

Stock$OpenTom[which(lastday)] <- NA
Stock$CloseTom[which(lastday)] <- NA

Stock
#  TickerID         Date Open Close OpenTom CloseTom
#1        A 0.0004967710 42.1  43.4    43.4     42.3
#2        A 0.0002483855 43.4  42.3    42.3     44.1
#3        A 0.0001655903 42.3  44.1      NA       NA
#4       AA 0.0004967710 28.7  28.9    28.9     28.4
#5       AA 0.0002483855 28.9  28.4    28.4     29.1
#6       AA 0.0001655903 28.4  29.1      NA       NA
#7      AAA 0.0004967710 61.1  62.1    62.1     63.5
#8      AAA 0.0002483855 62.1  63.5    63.5     64.4
#9      AAA 0.0001655903 63.5  64.4      NA       NA

You could use dplyr :

dat %>% group_by(TickerID) %>% mutate(OpenTom = ifelse(Date != max(Date),Close,NA),
    CloseTom = ifelse(Date != max(Date),Close[2:3],NA))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM