объединить периоды для получения временных последовательностей одновременно для разных начальных точек - PullRequest
0 голосов
/ 17 февраля 2019

У меня есть следующие данные в качестве примера:

library(data.table)
set.seed(42)
t <- data.table(time=1:1000, period=round(runif(100,1,5)))
p <- data.table(id=1:10, cut=sample(1:100,5))


> t[62:71]
    time period
 1:   62      5
 2:   63      4
 3:   64      3
 4:   65      4
 5:   66      2
 6:   67      2
 7:   68      4
 8:   69      4
 9:   70      2
10:   71      1

> head(p)
   id cut
1:  1  63
2:  2  22
3:  3  99
4:  4  38
5:  5  91
6:  6  63

, где t дает некоторый вектор periods, связанный с временными точками, а p дает каждому человеку отсечение в time.

Для каждого человека в p я хотел бы начать с отсечения этого человека и создать последовательность из 4 временных точек, объединяя periods.Например, для лица 1, начиная с момента 63, последовательность будет иметь вид 63, 63+4=67, 67+2=69 и 69+4=73.

В идеале, результат будет:

> head(res)
   id  t1   t2   t3   t4
    1  63   67   69   73
    2  22   24   29   32
    3  99  103  105  109
    4  38   40   43   44
    5  91   95  100  103
    6  63   67   69   73

Ранее я узнал, как создавать последовательности, используя accumulate::purrr ( итеративная сумма, где сумма определяет следующую позицию, которая будет добавлена ​​).Однако мне интересно, можно ли сделать что-то подобное одновременно для разных людей, использующих data.table или другие пакеты, но избегая циклов for, поскольку наборы данных довольно велики.


edit: версия, гдезначения времени не совпадают с указателями строк

library(data.table)
set.seed(42)
t <- data.table(time=1001:2000, period=round(runif(100,1,5)))
p <- data.table(id=1:10, cut=sample(1:100,5))

аналогично приведенному выше, за исключением

> t[62:71]
    time period
 1: 1062      5
 2: 1063      4
 3: 1064      3
 4: 1065      4
 5: 1066      2
 6: 1067      2
 7: 1068      4
 8: 1069      4
 9: 1070      2
10: 1071      1

, где t$time[i] не равно i, что запрещает Jaap'sПервое решение.

Ответы [ 2 ]

0 голосов
/ 17 февраля 2019

Я бы использовал петлю while().

while (ncol(p) - 1 < 4) {
  p <- cbind(p, p[[ncol(p)]] + t$period[p[[ncol(p)]]])
} 

> head(p)
   id cut  V2  V2  V2
1:  1  63  67  69  73
2:  2  22  24  29  32
3:  3  99 103 105 109
4:  4  38  40  43  44
5:  5  91  95 100 103
6:  6  63  67  69  73
0 голосов
/ 17 февраля 2019

Циклы For не обязательно плохие или неэффективные.При правильном использовании они могут быть эффективным решением вашей проблемы.

Для вашей текущей проблемы я бы использовал цикл for с пакетом , который эффективен, поскольку data.table обновляется по ссылке:

res <- p[, .(id, t1 = cut)]

for(i in 2:4) {
  res[, paste0("t",i) := t[res[[i]], time + period] ]
}

, что дает:

> res
    id t1  t2  t3  t4
 1:  1 63  67  69  73
 2:  2 22  24  29  32
 3:  3 99 103 105 109
 4:  4 38  40  43  44
 5:  5 91  95 100 103
 6:  6 63  67  69  73
 7:  7 22  24  29  32
 8:  8 99 103 105 109
 9:  9 38  40  43  44
10: 10 91  95 100 103

В качестве альтернативы, вы можете обновить p следующим образом:

for(i in 2:4) {
  p[, paste0("t",i) := t[p[[i]], time + period]]
}
setnames(p, "cut", "t1")

, который дает тот же результат.


Для обновленных данных примера вы должны изменить приведенный выше метод на:

for(i in 2:4) {
  p[, paste0("t",i) := t[match(p[[i]], t$time), time + period]]
}
setnames(p, "cut", "t1")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...