2013-11-28 5 views
2

Я застрял в довольно простой задаче для сбора данных. У меня есть транзакционной кадр данных в R, который напоминает этот один:Сохранение предыдущей даты в R

id<-c(11,11,22,22,22) 
dates<-as.Date(c('2013-11-15','2013-11-16','2013-11-15','2013-11-16','2013-11-17'), "%Y-%m-%d") 
example<-data.frame(id=id,dates=dates) 

    id  dates 
1 11 2013-11-15 
2 11 2013-11-16 
3 22 2013-11-15 
4 22 2013-11-16 
5 22 2013-11-17 

Я ищу способ, чтобы сохранить дату предыдущей операции. Результирующая таблица будет выглядеть следующим образом:

previous_dates<-as.Date(c('','2013-11-15','','2013-11-15','2013-11-16'), "%Y-%m-%d") 
example2<-data.frame(id=id,dates=dates, previous_dates=previous_dates) 

    id  dates previous_dates 
1 11 2013-11-15   <NA> 
2 11 2013-11-16  2013-11-15 
3 22 2013-11-15   <NA> 
4 22 2013-11-16  2013-11-15 
5 22 2013-11-17  2013-11-16 

Я смотрел на другие подобные проблемы, и одно решение, которое очень близко к тому, что я хочу это:

library(data.table) 
dt <- as.data.table(example) 

prev_date <- function(x) c(x[1],x) 

dt[,prev:=prev_date(dates), by=id] 

Проблема с этим в том, что если нет предыдущей даты (, как и в случае J = 11 дат = 2013-11-15) функции будет выводить то же день в результате:

id  dates previous_dates 
1 11 2013-11-15  2013-11-15 
2 11 2013-11-16  2013-11-15 

Может кто-нибудь помочь, пожалуйста?

ответ

3
example$previous_dates <- ave(example$dates, example$id, 
       FUN= function(dt) c.Date(c(NA, dt[-length(dt)]) 
              )) 
> example 
    id  dates previous_dates 
1 11 2013-11-15   <NA> 
2 11 2013-11-16  2013-11-15 
3 22 2013-11-15   <NA> 
4 22 2013-11-16  2013-11-15 
5 22 2013-11-17  2013-11-16 

Игра вокруг с классами Дата объектов .... это также работает:

example$previous_dates <- ave(example$dates, example$id, 
      FUN= function(dt) structure( 
            c(NA, dt[-length(dt)]), 
            class="Date") ) 
+0

Этот тоже работает. Спасибо DWin! –

+0

На самом деле ваше решение работает быстрее, чем Roland при применении к большому набору данных. –

+0

@NikolayNenov Если ваш набор данных действительно большой и есть много идентификаторов, вы должны использовать data.table. Я только вчера не показывал, как это сделать, потому что я не нашел решения для сохранения класса Date и ему нужно было бы сделать что-то вроде Dwin, используемого в первой ревизии его ответа. – Roland

4
library(plyr) 
example <- ddply(example, .(id), transform, 
            previous_dates=c(as.Date(NA), head(dates, -1))) 
    id  dates previous_dates 
1 11 2013-11-15   <NA> 
2 11 2013-11-16  2013-11-15 
3 22 2013-11-15   <NA> 
4 22 2013-11-16  2013-11-15 
5 22 2013-11-17  2013-11-16 
+1

Мне нравится as.Date (NA). Мне нужно было переустановить с as.Date.numeric после того, как c() удалил мой класс Date. –

+2

@DWin 'c.Date (NA, head (даты, -1))' также будет работать. – Roland

+0

Итак, это явление отправки S3? Первый аргумент выигрывает, а NA «не имеет класса». –

1

Просто другой подход:

transform(example, previous_dates = ave(dates, id, FUN = 
             function(x) x[c(NA, (seq_along(x)-1))])) 

    id  dates previous_dates 
1 11 2013-11-15   <NA> 
2 11 2013-11-16  2013-11-15 
3 22 2013-11-15   <NA> 
4 22 2013-11-16  2013-11-15 
5 22 2013-11-17  2013-11-16 
Смежные вопросы