#r #group-by #data.table
#r #группировка по #data.table
Вопрос:
Извиняюсь за неясное описание, но я не думаю, что однострочный текст мог бы объяснить требование, которое у меня есть.
У меня есть data.table dt1
, как показано ниже:
id pg pd dt capp vt
1: 1111 hm <NA> 20-10-2020 21:07:54 NA 5
2: 1111 abc abc 20-10-2020 21:07:53 1234 5
3: 1111 hm <NA> 20-10-2020 16:07:56 NA 4
4: 1111 cde <NA> 20-10-2020 16:06:57 NA 4
5: 1111 cde <NA> 20-10-2020 16:05:58 NA 4
6: 1111 def def 20-07-2020 12:07:59 345 3
7: 1111 abc <NA> 20-06-2020 22:07:59 NA 2
8: 1111 def <NA> 20-06-2020 22:07:58 NA 2
9: 1111 abc <NA> 20-05-2020 21:07:59 NA 1
10: 1112 hm <NA> 20-10-2020 21:07:52 NA 4
11: 1112 cde cde 20-10-2020 21:07:39 456 4
12: 1112 hm <NA> 20-10-2020 16:07:56 NA 3
13: 1112 abc <NA> 20-10-2020 16:06:57 NA 3
14: 1112 abc <NA> 20-07-2020 16:05:58 NA 2
15: 1112 def abc 20-07-2020 16:04:59 234 2
16: 1112 cde <NA> 20-06-2020 22:07:59 NA 1
17: 1112 def <NA> 20-06-2020 21:07:59 NA 1
18: 1112 cde <NA> 20-05-2020 21:07:59 NA 0
Требование заключается в следующем: Я хочу создать новую переменную prev
, которая для заданного id
и capp
(где capp
нет null
) имеет max
значение vt
where:
vt
меньше значенияvt
, соответствующего ненулевомуcapp
и
pg
равно значению вpd
, соответствующему ненулевомуcapp
Мой ожидаемый результат будет выглядеть следующим образом:
id pg pd dt capp vt prev
1: 1111 hm <NA> 20-10-2020 21:07:54 NA 5 <NA>
2: 1111 abc abc 20-10-2020 21:07:53 1234 5 2
3: 1111 hm <NA> 20-10-2020 16:07:56 NA 4 <NA>
4: 1111 cde <NA> 20-10-2020 16:06:57 NA 4 <NA>
5: 1111 cde <NA> 20-10-2020 16:05:58 NA 4 <NA>
6: 1111 def def 20-07-2020 12:07:59 345 3 2
7: 1111 abc <NA> 20-06-2020 22:07:59 NA 2 <NA>
8: 1111 def <NA> 20-06-2020 22:07:58 NA 2 <NA>
9: 1111 abc <NA> 20-05-2020 21:07:59 NA 1 <NA>
10: 1112 hm <NA> 20-10-2020 21:07:52 NA 4 <NA>
11: 1112 cde cde 20-10-2020 21:07:39 456 4 1
12: 1112 hm <NA> 20-10-2020 16:07:56 NA 3 <NA>
13: 1112 abc <NA> 20-10-2020 16:06:57 NA 3 <NA>
14: 1112 abc <NA> 20-07-2020 16:05:58 NA 2 <NA>
15: 1112 def abc 20-07-2020 16:04:59 234 2 NA/Inf
16: 1112 cde <NA> 20-06-2020 22:07:59 NA 1 <NA>
17: 1112 def <NA> 20-06-2020 21:07:59 NA 1 <NA>
18: 1112 cde <NA> 20-05-2020 21:07:59 NA 0 <NA>
dt1
определение, как указано ниже:
structure(list(id = c(1111L, 1111L, 1111L, 1111L, 1111L, 1111L,
1111L, 1111L, 1111L, 1112L, 1112L, 1112L, 1112L, 1112L, 1112L,
1112L, 1112L, 1112L), pg = c("hm", "abc", "hm", "cde", "cde",
"def", "abc", "def", "abc", "hm", "cde", "hm", "abc", "abc",
"def", "cde", "def", "cde"), pd = c(NA, "abc", NA, NA, NA, "def",
NA, NA, NA, NA, "cde", NA, NA, NA, "abc", NA, NA, NA), dt = c("20-10-2020 21:07:54",
"20-10-2020 21:07:53", "20-10-2020 16:07:56", "20-10-2020 16:06:57",
"20-10-2020 16:05:58", "20-07-2020 12:07:59", "20-06-2020 22:07:59",
"20-06-2020 22:07:58", "20-05-2020 21:07:59", "20-10-2020 21:07:52",
"20-10-2020 21:07:39", "20-10-2020 16:07:56", "20-10-2020 16:06:57",
"20-07-2020 16:05:58", "20-07-2020 16:04:59", "20-06-2020 22:07:59",
"20-06-2020 21:07:59", "20-05-2020 21:07:59"), capp = c(NA, 1234L,
NA, NA, NA, 345L, NA, NA, NA, NA, 456L, NA, NA, NA, 234L, NA,
NA, NA), vt = c(5L, 5L, 4L, 4L, 4L, 3L, 2L, 2L, 1L, 4L, 4L, 3L,
3L, 2L, 2L, 1L, 1L, 0L)), .Names = c("id", "pg", "pd", "dt",
"capp", "vt"), row.names = c(NA, -18L), class = c("data.table",
"data.frame"), .internal.selfref = <pointer: 0x0000000002650788>)
Комментарии:
1. Насколько я могу судить, вы никогда не рассматриваете строки, где
capp
находитсяNA
, и все значения вprev
получены изvt
столбца. Тогда, как вы можете получить a2
во второй строкеprev
, какcapp
всегдаNA
, когдаvt
2
дляid = 1111
?2. @ekoam: Я понимаю, откуда вы. vt меньше значения vt, соответствующего ненулевому capp , на самом деле, я ищу значения
vt
(гдеcapp
может быть null), но меньше значенияvt
из строки, гдеcapp
не равно null (следовательно, соответствует ненулевому capp )
Ответ №1:
Вот еще один вариант, использующий неравнозначное объединение для каждой строки ненулевого capp и затем обновляющий по ссылке:
dt1[!is.na(capp), prev :=
dt1[.SD, on=.(id, pg=pd, vt<vt), max(x.vt), by=.EACHI]$V1
]
Комментарии:
1. Вы дали мне немного пищи для размышлений. Спасибо за вашу помощь.
2. Любопытно, если мне нужно добавить еще одно условие, что-то вроде
pg!="cc"
, войдет ли это вon()
?3.
dt1[!is.na(capp), prev := dt1[.SD, on=.(id, pg=pd, vt<vt), max(x.vt[pg!="cc"]), by=.EACHI]$V1 ]
. Это сработало для меня, но сделало его немного медленнее.
Ответ №2:
Это то, что вам нужно?
dt1[,
prev := with(.SD, vapply(
seq_along(vt),
function(i) {tmp <- vt[vt < vt[[i]] amp; pg == pd[[i]] amp; !is.na(capp[[i]])]; if (length(tmp) < 1L) NA_real_ else max(tmp)},
numeric(1L)
)),
by = id
]
Вывод
id pg pd dt capp vt prev
1: 1111 hm <NA> 20-10-2020 21:07:54 NA 5 NA
2: 1111 abc abc 20-10-2020 21:07:53 1234 5 2
3: 1111 hm <NA> 20-10-2020 16:07:56 NA 4 NA
4: 1111 cde <NA> 20-10-2020 16:06:57 NA 4 NA
5: 1111 cde <NA> 20-10-2020 16:05:58 NA 4 NA
6: 1111 def def 20-07-2020 12:07:59 345 3 2
7: 1111 abc <NA> 20-06-2020 22:07:59 NA 2 NA
8: 1111 def <NA> 20-06-2020 22:07:58 NA 2 NA
9: 1111 abc <NA> 20-05-2020 21:07:59 NA 1 NA
10: 1112 hm <NA> 20-10-2020 21:07:52 NA 4 NA
11: 1112 cde cde 20-10-2020 21:07:39 456 4 1
12: 1112 hm <NA> 20-10-2020 16:07:56 NA 3 NA
13: 1112 abc <NA> 20-10-2020 16:06:57 NA 3 NA
14: 1112 abc <NA> 20-07-2020 16:05:58 NA 2 NA
15: 1112 def abc 20-07-2020 16:04:59 234 2 NA
16: 1112 cde <NA> 20-06-2020 22:07:59 NA 1 NA
17: 1112 def <NA> 20-06-2020 21:07:59 NA 1 NA
18: 1112 cde <NA> 20-05-2020 21:07:59 NA 0 NA
Комментарии:
1. Это работает, но мучительно медленно. Спасибо за вашу помощь.