Условно определяя значение столбца, посмотрев на последнюю группу - PullRequest
6 голосов
/ 26 марта 2020

У меня есть тестовые данные, которые выглядят так:

   Group Value
1      a     1
2      a     2
3      a     3
4      a     4
5      b     5
6      b     2
7      b     3
8      c     6
9      c     7
10     c     8
11     c     3
12     c     6
13     d     9
14     d    10
15     e     9

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

   Group Value In_Last_Group
1      a     1         FALSE
2      a     2         FALSE
3      a     3         FALSE
4      a     4         FALSE
5      b     5         FALSE
6      b     2          TRUE
7      b     3          TRUE
8      c     6         FALSE
9      c     7         FALSE
10     c     8         FALSE
11     c     3          TRUE
12     c     5          TRUE
13     d     9         FALSE
14     d    10         FALSE
15     e     9          TRUE

У меня есть способ сделать это, используя стандарт для l oop, но у меня большой набор данных, и я считаю, что это будет намного быстрее если бы это было векторизация. Любая помощь будет оценена.

Вот dput данных испытаний:

structure(list(Group = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 4L, 4L, 5L), .Label = c("a", "b", "c", "d", 
"e"), class = "factor"), Value = c(1, 2, 3, 4, 5, 2, 3, 6, 7, 
8, 3, 6, 9, 10, 9)), .Names = c("Group", "Value"), row.names = c(NA, 
-15L), class = "data.frame")

Ответы [ 2 ]

4 голосов
/ 27 марта 2020

Мы можем nest после группировки по «Группе», затем удалить первый и последний элементы столбца «данные», использовать map2, чтобы сделать сравнение соответствующих элементов, а затем добавить с элементами FALSE для первая группа

library(dplyr)
library(purrr)
df2 <- df1 %>%
         group_by(Group) %>%
         nest

flag <-  map2(df2$data[-1], df2$data[-nrow(df2)], ~ 
      .x$Value %in% .y$Value) %>%
      unlist
df1$Last_Group <- c(rep(FALSE, nrow(df2$data[[1]])), flag)
2 голосов
/ 27 марта 2020

Вы можете использовать объединение для поиска значений в предыдущей группе, чтобы увидеть, существуют ли эти значения. Это должно быть быстрее, чем проходить по группам. Я не знаком с tidyverse, но вот реализация в data.table (которая также должна быть быстрее, чем tidyverse, если ваши данные достаточно велики): вывод

library(data.table)
setDT(DF)
DF[, c("g", "pg") := .(r <- rleid(Group), r - 1L)]
DF[, ilg := FALSE][DF, on=.(pg=g, Value), ilg := TRUE]

(обратите внимание, что есть опечатка для значения в строке 12 требуемого вывода OP):

    Group Value g pg   ilg
 1:     a     1 1  0 FALSE
 2:     a     2 1  0 FALSE
 3:     a     3 1  0 FALSE
 4:     a     4 1  0 FALSE
 5:     b     5 2  1 FALSE
 6:     b     2 2  1  TRUE
 7:     b     3 2  1  TRUE
 8:     c     6 3  2 FALSE
 9:     c     7 3  2 FALSE
10:     c     8 3  2 FALSE
11:     c     3 3  2  TRUE
12:     c     6 3  2 FALSE
13:     d     9 4  3 FALSE
14:     d    10 4  3 FALSE
15:     e     9 5  4  TRUE

data:

DF <- structure(list(Group = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
3L, 3L, 3L, 3L, 3L, 4L, 4L, 5L), .Label = c("a", "b", "c", "d", 
"e"), class = "factor"), Value = c(1, 2, 3, 4, 5, 2, 3, 6, 7, 
8, 3, 6, 9, 10, 9)), .Names = c("Group", "Value"), row.names = c(NA, 
-15L), class = "data.frame")
...