Как эффективно обновить data.table Условно для связанной записи в data.frame Существующий? - PullRequest
0 голосов
/ 14 сентября 2018

Рассмотрим таблицу данных, dt:

   id boro block       date
 1:  1    1     1 01/01/1991
 2:  1    1     2 01/01/1991
 3:  1    2     3 01/01/1991
 4:  1    2     4 01/01/1991
 5:  2    1     1 01/01/1992
 6:  2    1     2 01/01/1992
 7:  2    2     3 01/01/1992
 8:  2    2     5 01/01/1992
 9:  3    1     1 01/01/1993
10:  3    1     2 01/01/1993
11:  3    2     6 01/01/1993
12:  3    2     7 01/01/1993

То, что я хочу сделать эффективно (у меня 19 миллионов строк, 70 столбцов), - это для каждой строки проверить, существует ли идентификатор + 1, boro, запись блока в dt. Если это так, создайте новый столбец, end_date, с датой id + 1, boro, блок записи. I

Код для каждой строки будет выглядеть примерно так:

update_end_date <- function(dt,Id,Boro,Block) {
  if (dt[id==(Id+1) & boro==Boro & block==Block,.N]==1) {
    return(dt[id==(Id+1) & boro==Boro & block==Block,date])
  }
}

Я повторяю функцию по строкам, используя:

dt[,end_date := update_end_date(dt,id,boro,block), by = seq_len(nrow(dt))]

В результате получится таблица:

    id boro block       date   end_date
 1:  1    1     1 01/01/1991 01/01/1992
 2:  1    1     2 01/01/1991 01/01/1992
 3:  1    2     3 01/01/1991 01/01/1992
 4:  1    2     4 01/01/1991         NA
 5:  2    1     1 01/01/1992 01/01/1993
 6:  2    1     2 01/01/1992 01/01/1993
 7:  2    2     3 01/01/1992         NA
 8:  2    2     5 01/01/1992         NA
 9:  3    1     1 01/01/1993         NA
10:  3    1     2 01/01/1993         NA
11:  3    2     6 01/01/1993         NA
12:  3    2     7 01/01/1993         NA

Это работает, но невероятно медленно. Исходя из моих наблюдений, он зацикливается на 100 строк за 80 секунд, поэтому мне потребовались бы эоны, чтобы пробежать 19 миллионов строк. Я плохо знаком с R, поэтому должно быть лучшее решение, о котором я не знаю.

1 Ответ

0 голосов
/ 14 сентября 2018

Работа с соединениями, а не с циклами строк, должна выполняться намного быстрее:

dat[, idp1 := id + 1]
dat[dat, on=c("idp1"="id","boro","block"), end_date := i.date]
dat

#    id boro block       date idp1   end_date
# 1:  1    1     1 01/01/1991    2 01/01/1992
# 2:  1    1     2 01/01/1991    2 01/01/1992
# 3:  1    2     3 01/01/1991    2 01/01/1992
# 4:  1    2     4 01/01/1991    2         NA
# 5:  2    1     1 01/01/1992    3 01/01/1993
# 6:  2    1     2 01/01/1992    3 01/01/1993
# 7:  2    2     3 01/01/1992    3         NA
# 8:  2    2     5 01/01/1992    3         NA
# 9:  3    1     1 01/01/1993    4         NA
#10:  3    1     2 01/01/1993    4         NA
#11:  3    2     6 01/01/1993    4         NA
#12:  3    2     7 01/01/1993    4         NA
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...