Заменить ячейки, когда последовательность элементов строки идентифицирована во фрейме данных - PullRequest
0 голосов
/ 21 февраля 2019

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

df <- data.frame(c(1,1,1,2,2,2,3,3,3),c(TRUE,FALSE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,FALSE), 
           c(0,3,0,5,5,0,0,0,7), c("a","b","c","d","a","b","c","d","a"))
colnames(df) <- c("ID", "Status", "Number", "Letter")

  ID Status Number Letter
1  1   TRUE      0      a
2  1  FALSE      3      b
3  1   TRUE      0      c
4  2  FALSE      5      d
5  2  FALSE      5      a
6  2   TRUE      0      b
7  3   TRUE      0      c
8  3   TRUE      0      d
9  3  FALSE      7      a

По сути, я хочу идентифицировать идентификаторы, для которых TRUE встречается до FALSE.Затем я хочу заменить Status и Number в строках, которые показывают TRUE (т.е. строки 1,7,8), на следующую строку FALSE (то есть строки 2,9,9).Окончательный результат должен выглядеть следующим образом:

  ID Status Number Letter
1  1  FALSE      3      a
2  1  FALSE      3      b
3  1   TRUE      0      c
4  2  FALSE      5      d
5  2  FALSE      5      a
6  2   TRUE      0      b
7  3  FALSE      7      c
8  3  FALSE      7      d
9  3  FALSE      7      a

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

Пока что из этого поста ( R - Определить последовательность элементов строки по группам в кадре данных ) мне удалось получить первую часть:

library(tidyverse)
extract <- df %>% group_by(ID) %>%
  filter(ifelse(Status == FALSE,
                lag(Status) == TRUE,
                lead(Status) == FALSE)) 

# A tibble: 4 x 4
# Groups:   ID [2]
     ID Status Number Letter
  <dbl> <lgl>   <dbl> <fct> 
1    1. TRUE       0. a     
2    1. FALSE      3. b     
3    3. TRUE       0. d     
4    3. FALSE      7. a  

Мне бы очень хотелосьпризнателен за любую помощь, как действовать отсюда.Я попытался задать свой вопрос как можно точнее, дайте мне знать, если что-то неясно.


Редактировать: Следуя совету @ Хенрика, я добавлю немного больше сложности в свой вопрос.Этот набор данных должен работать в этом отношении:

df <- data.frame(c(1,1,1,2,2,2,3,3,3,4,4,4,4,4),c(TRUE,TRUE,TRUE,FALSE,FALSE,TRUE,TRUE,TRUE,
                                                  FALSE,TRUE,FALSE,TRUE,FALSE,TRUE), 
                 c(0,0,0,5,5,0,0,0,7,0,6,0,3,0), c("a","b","c","d","a","b","c","d","a","b",
                                                   "c","d","a","b"))
colnames(df) <- c("ID", "Status", "Number", "Letter")

> df
   ID Status Number Letter
1   1   TRUE      0      a
2   1   TRUE      0      b
3   1   TRUE      0      c
4   2  FALSE      5      d
5   2  FALSE      5      a
6   2   TRUE      0      b
7   3   TRUE      0      c
8   3   TRUE      0      d
9   3  FALSE      7      a
10  4   TRUE      0      b
11  4  FALSE      6      c
12  4   TRUE      0      d
13  4  FALSE      3      a
14  4   TRUE      0      b

Вот мое предлагаемое решение, которое, однако, не работает для отдельных строк (ср. 12):

df2 <- df %>% 
  group_by(ID) %>%
  mutate(Status2 = if (!all(Status)) replace(Status, cumsum(!Status) < 1, FALSE) else TRUE,
         Number2 = if (!all(Status)) replace(Number, cumsum(!Status) < 1,
                                                      first(Number[Status == FALSE])) 
                   else first(replace(Number, cumsum(!Status) < 1, Number[Status == TRUE])))

> df2
# A tibble: 14 x 6
# Groups:   ID [4]
      ID Status Number Letter Status2 Number2
   <dbl> <lgl>   <dbl> <fct>  <lgl>     <dbl>
 1    1. TRUE       0. a      TRUE         0.
 2    1. TRUE       0. b      TRUE         0.
 3    1. TRUE       0. c      TRUE         0.
 4    2. FALSE      5. d      FALSE        5.
 5    2. FALSE      5. a      FALSE        5.
 6    2. TRUE       0. b      TRUE         0.
 7    3. TRUE       0. c      FALSE        7.
 8    3. TRUE       0. d      FALSE        7.
 9    3. FALSE      7. a      FALSE        7.
10    4. TRUE       0. b      FALSE        6.
11    4. FALSE      6. c      FALSE        6.
12    4. TRUE       0. d      TRUE         0.
13    4. FALSE      3. a      FALSE        3.
14    4. TRUE       0. b      TRUE         0.

Результат дляЧисло 2 в строке 12 должно соответствовать следующей строке, т. Е. Быть 3.

Ответы [ 2 ]

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

Другой вариант, где мы replace все значения, для которых cumsum(!Status) < 1 равно TRUE с FALSE, то есть все значения до того, как будет заменен первый FALSE.

df %>% 
  group_by(ID) %>% 
  mutate(new_status = replace(Status, cumsum(!Status) < 1, FALSE))
# A tibble: 9 x 5
# Groups:   ID [3]
#     ID Status Number Letter new_status
#  <dbl> <lgl>   <dbl> <fct>  <lgl>     
#1     1 TRUE        0 a      FALSE     
#2     1 FALSE       3 b      FALSE     
#3     1 TRUE        0 c      TRUE      
#4     2 FALSE       5 d      FALSE     
#5     2 FALSE       5 a      FALSE     
#6     2 TRUE        0 b      TRUE      
#7     3 TRUE        0 c      FALSE     
#8     3 TRUE        0 d      FALSE     
#9     3 FALSE       7 a      FALSE 
0 голосов
/ 21 февраля 2019

Вы можете сделать:

library(dplyr)

df %>%
  group_by(ID) %>%
  mutate(flag = coalesce(Status == TRUE &
                           lead(Status == FALSE), FALSE)) %>%
  group_by(ID, grp = cumsum(+(Status != lag(Status, default = "rndom")))) %>%
  mutate(Status = ifelse(any(flag == TRUE), FALSE, Status)) %>% ungroup() %>%
  select(-flag, -grp)

Вывод:

# A tibble: 9 x 4
     ID Status Number Letter
  <dbl> <lgl>   <dbl> <fct> 
1     1 FALSE       0 a     
2     1 FALSE       3 b     
3     1 TRUE        0 c     
4     2 FALSE       5 d     
5     2 FALSE       5 a     
6     2 TRUE        0 b     
7     3 FALSE       0 c     
8     3 FALSE       0 d     
9     3 FALSE       7 a     
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...