2016-11-09 4 views
0
> a 
    UID Date.of.Txn 
1 1 09-11-2016 
2 1 25-10-2016 
3 1 30-08-2016 
4 2 30-08-2016 
5 2 02-06-2016 
6 3 18-04-2016 
7 3 31-01-2016 
8 4 03-11-2015 
9 4 06-08-2015 
10 5 20-05-2015 
11 5 08-05-2015 

Что я хочу, так это то, что за каждые UID необходимо вернуть вторую последнюю дату w.r.t. к его значению в колонке Date.of.Txn.Возврат второй последней даты

Для например

для UID = 1 и Date.of.Txn = 09-11-2016

последняя дата Txn на 09-11-2016 для ID = 1 был 25-10-2016 аналогично для

UID = 1 и Date.of.Txn 25-10-2016 последняя дата Txn на 25-10-2016 для ID = 1 был 30-08-2016

и

так как нет доступной даты UID = 1 и Date of Txn = 30-08-2016 значения в столбце Datesorted будет 0, как показано ниже.

> result 
    UID Date.of.Txn Datesorted 
1 1 09-11-2016 25-10-2016 
2 1 25-10-2016 30-08-2016 
3 1 30-08-2016   0 
4 2 30-08-2016 02-06-2016 
5 2 02-06-2016   0 
6 3 18-04-2016 31-01-2016 
7 3 31-01-2016   0 
8 4 03-11-2015 06-08-2015 
9 4 06-08-2015   0 
10 5 20-05-2015 08-05-2015 
11 5 08-05-2015   0 

Любые идеи?

+1

Вы можете использовать dplyr и его функции ввода/запаздывания. https://cran.r-project.org/web/packages/dplyr/vignettes/window-functions.html – PhillipD

ответ

0

Это также будет работать (без изменения формата даты на выходе):

do.call(rbind, lapply(split(a, a$UID), function(x){ 
    x <- x[order(as.Date(as.character(x$Date.of.Txn), format='%d-%m-%Y'), decreasing=TRUE),] 
    x$Datesorted <- c(as.character(x$Date.of.Txn[2:nrow(x)]),'0')  
    x})) 

    UID Date.of.Txn Datesorted 
1.1 1 09-11-2016 25-10-2016 
1.2 1 25-10-2016 30-08-2016 
1.3 1 30-08-2016   0 
2.4 2 30-08-2016 02-06-2016 
2.5 2 02-06-2016   0 
3.6 3 18-04-2016 31-01-2016 
3.7 3 31-01-2016   0 
4.8 4 03-11-2015 06-08-2015 
4.9 4 06-08-2015   0 
5.10 5 20-05-2015 08-05-2015 
5.11 5 08-05-2015   0 
+0

Спасибо Сандипан. Можете ли вы объяснить код, пожалуйста? –

+0

уверенный @pankaj. Сначала нам нужно разделить данные по UID, для каждого UID мы будем иметь фрейм данных. Теперь отсортируйте каждый фрейм данных w.r.t. время в порядке убывания времени (если оно еще не отсортировано), чтобы убедиться, что дата, которая появляется первым для любого данного UID, на самом деле является последней датой (время w.r.t.). Тогда просто нужно добавить столбец Datesorted с запаздывающей версией столбца Date.of.Txn с добавлением дополнительного нуля. –

0

Полагаю, что то, что требуется, - это временная дата в пределах UID для каждой даты.

Определите функцию prev_date, которая задает вектор дат, который находит предыдущий для каждого (или NA, если нет). Convert Date.of.Txn до "Date" класс. Наконец, примените prev_date по UID, используя by. Пакеты не используются.

prev_date <- function(d) { 
    do.call("c", lapply(d, function(d0) if (any(d < d0)) max(d[d < d0]) else NA)) 
} 

a2 <- transform(a, Date.of.Txn = as.Date(Date.of.Txn, "%d-%m-%Y")) 
do.call("rbind", by(a2, a2$UID, transform, prev_date = prev_date(Date.of.Txn))) 

В результате:

 UID Date.of.Txn prev_date 
1.1 1 2016-11-09 2016-10-25 
1.2 1 2016-10-25 2016-08-30 
1.3 1 2016-08-30  <NA> 
2.4 2 2016-08-30 2016-06-02 
2.5 2 2016-06-02  <NA> 
3.6 3 2016-04-18 2016-01-31 
3.7 3 2016-01-31  <NA> 
4.8 4 2015-11-03 2015-08-06 
4.9 4 2015-08-06  <NA> 
5.10 5 2015-05-20 2015-05-08 
5.11 5 2015-05-08  <NA> 

Примечание: вход a в воспроизводимом виде (это должно быть предусмотрено в вопросе) является:

a <- structure(list(UID = c(1L, 1L, 1L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 
5L), Date.of.Txn = structure(c(5L, 8L, 9L, 9L, 1L, 6L, 10L, 2L, 
3L, 7L, 4L), .Label = c("02-06-2016", "03-11-2015", "06-08-2015", 
"08-05-2015", "09-11-2016", "18-04-2016", "20-05-2015", "25-10-2016", 
"30-08-2016", "31-01-2016"), class = "factor")), .Names = c("UID", 
"Date.of.Txn"), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5", "6", "7", "8", "9", "10", "11"))