Пометить строки между двумя значениями столбца в группе с помощью dplyr - PullRequest
0 голосов
/ 06 декабря 2018

У меня есть фиктивные данные, как показано ниже

df = data.frame(name = c(rep("Anna",8),rep("Jenny",7)),
                id = c(100,100,100,100,100,100,100,100,250,250,250,250,250,250,250),
                time = c("t2","t3","t5","t1","t7","t2","t1","t5","t1","t2","t6","t2","t8","t6","t5"),                stringsAsFactors = F)

> df
    name  id time
1   Anna 100   t2
2   Anna 100   t3
3   Anna 100   t5
4   Anna 100   t1
5   Anna 100   t7
6   Anna 100   t2
7   Anna 100   t1
8   Anna 100   t5
9  Jenny 250   t1
10 Jenny 250   t2
11 Jenny 250   t6
12 Jenny 250   t2
13 Jenny 250   t8
14 Jenny 250   t6
15 Jenny 250   t5

Мой ожидаемый результат для каждой группы id, я хочу flag значений между t2 и * включительно1008 * t5 с использованием переменной time - в каждой группе будет несколько таких случаев, и код должен быть в состоянии исключить некоторые неработающие случаи, как в примере ниже

 > df
    name  id time Flag
1   Anna 100   t2    1
2   Anna 100   t3    1
3   Anna 100   t5    1
4   Anna 100   t1    0
5   Anna 100   t7    0
6   Anna 100   t2    1
7   Anna 100   t1    1
8   Anna 100   t5    1
9  Jenny 250   t1    0
10 Jenny 250   t2    0
11 Jenny 250   t6    0
12 Jenny 250   t2    1
13 Jenny 250   t8    1
14 Jenny 250   t6    1
15 Jenny 250   t5    1

Прошуэто используя режим dplyr(), так как я могу добавить больше группирующих переменных в будущем для масштабируемости.Я искал, как использовать which() внутри функций dplyr, не очень много, я нашел здесь один эквивалент Python Получить строки между двумя значениями столбца, используя Python

Edit1: у меня естьнесколько разделов t2-t5 в каждой группе, которые необходимо пометить.Спасибо @ronak за то, что подняли его

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Ниже приведен простой подход, который вы могли бы рассмотреть:

library(dplyr)

df %>%
    mutate(flag = ifelse(time %in% c("t2", "t3", "t4", "t5"), 1, 0))

Это помечает данные, как вы описали, и доступно для чтения.

   name  id time flag
1  Anna 100   t2    1
2  Anna 100   t3    1
3  Anna 100   t5    1
4 Jenny 250   t1    0
5 Jenny 250   t2    1
6 Jenny 250   t3    1
7 Jenny 250   t4    1
8 Jenny 250   t5    1
0 голосов
/ 06 декабря 2018

Должен быть лучший вариант для этого, но это работает

library(tidyverse)

df %>%
  group_by(name) %>%
  mutate(flag  = +(row_number() %in% which(time == "t2"):which(time == "t5")))


#  name     id time   flag
#  <chr> <dbl> <chr> <dbl>
#1 Anna    100 t2        1
#2 Anna    100 t3        1
#3 Anna    100 t5        1
#4 Jenny   250 t1        0
#5 Jenny   250 t2        1
#6 Jenny   250 t3        1
#7 Jenny   250 t4        1
#8 Jenny   250 t5        1

Это предполагает, что у вас есть только один "t2" и "t5" в каждой группе.

Та же логика с использованием базы R ave

as.numeric(with(df, ave(time, name, FUN = function(x) 
      +(1:length(x) %in% which(x == "t2"):which(x == "t5")))))
#[1] 1 1 1 0 1 1 1 1

РЕДАКТИРОВАНИЕ

Если у вас есть несколько «t2» и «t5», нет необходимостипринимать во внимание группу, так как вы все равно хотите пометить их.Мы можем использовать mapply и создать последовательность индексов, чтобы пометить флаг как 1.

df$flag <- 0
df$flag[unlist(mapply(":", which(df$time == "t2"), which(df$time == "t5")))] <- 1

, а версия dplyr для него равна

df %>%
  mutate(flag = +(row_number() %in% 
          unlist(map2(which(time == "t2"), which(time == "t5"), seq))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...