Как изменить значения последующих строк, если какое-либо условие выполняется для нескольких групп? - PullRequest
0 голосов
/ 22 февраля 2019

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

ID  value   condition
A   0         0
A   3         0
A   0         1
A   7         1
A   5         0
A   5         0
A   5         0
A   7         0
B   6         0
B   2         1
B   7         0
B   10        1
B   0         0
B   6         0

Я хочу изменить имя идентификатора при выполнении условия и изменить имя идентификатора, который следует за ним.Условие может быть выполнено несколько раз для каждого идентификатора, поэтому я хотел бы изменить его каждый раз.

Результат изменит исходный идентификатор или просто добавит новый столбец:

ID  value   condition   newID
A   0              0    A
A   3              0    A
A   0              1    A1
A   7              1    A1
A   5              0    A2
A   5              0    A2
A   5              0    A2
A   7              0    A2
B   6              0    B
B   2              1    B1
B   7              0    B2
B   10             1    B3
B   0              0    B4
B   6              0    B4

Ответы [ 4 ]

0 голосов
/ 31 августа 2019

Если я правильно понимаю, ОП хочет создать подгруппы в каждой ID для каждой непрерывной серии condition.

К сожалению, ФП попросил назвать подгруппы особым образом, что делает решения слишком сложными.По запросу OP должны быть названы подгруппы, например, A, A1, A2, что означает, что нумерация и имя подгруппы отключены на единицу, например, вторая подгруппа названа A1, третья A2 и т. Д.

В случае, если приемлема более упрощенная схема именования, мы можем напрямую воспользоваться параметром prefix функции rleid().Тогда первая подгруппа группы A будет названа A1, вторая A2 и т. Д.

dplyr

library(dplyr)
df %>% 
  group_by(ID) %>% 
  mutate(newID = data.table::rleid(condition, prefix = first(ID)))
# A tibble: 14 x 4
# Groups:   ID [2]
   ID    value condition newID
   <chr> <int>     <int> <chr>
 1 A         0         0 A1   
 2 A         3         0 A1   
 3 A         0         1 A2   
 4 A         7         1 A2   
 5 A         5         0 A3   
 6 A         5         0 A3   
 7 A         5         0 A3   
 8 A         7         0 A3   
 9 B         6         0 B1   
10 B         2         1 B2   
11 B         7         0 B3   
12 B        10         1 B4   
13 B         0         0 B5   
14 B         6         0 B5

data.table

library(data.table)
setDT(df)[, newID := rleid(condition, prefix = ID), ID][]
    ID value condition newID
 1:  A     0         0    A1
 2:  A     3         0    A1
 3:  A     0         1    A2
 4:  A     7         1    A2
 5:  A     5         0    A3
 6:  A     5         0    A3
 7:  A     5         0    A3
 8:  A     7         0    A3
 9:  B     6         0    B1
10:  B     2         1    B2
11:  B     7         0    B3
12:  B    10         1    B4
13:  B     0         0    B5
14:  B     6         0    B5

Data

library(data.table)
df <- fread("ID  value   condition
A   0         0
A   3         0
A   0         1
A   7         1
A   5         0
A   5         0
A   5         0
A   7         0
B   6         0
B   2         1
B   7         0
B   10        1
B   0         0
B   6         0")
0 голосов
/ 22 февраля 2019

Может также сделать:

library(dplyr)

df %>%
  group_by(ID) %>%
  mutate(newID = cumsum(c(0, (condition != lag(condition))[-1])),
         newID = ifelse(newID != 0, paste0(ID, newID), ID))

Вывод:

# A tibble: 14 x 4
# Groups:   ID [2]
   ID    value condition newID
   <chr> <int>     <int> <chr>
 1 A         0         0 A    
 2 A         3         0 A    
 3 A         0         1 A1   
 4 A         7         1 A1   
 5 A         5         0 A2   
 6 A         5         0 A2   
 7 A         5         0 A2   
 8 A         7         0 A2   
 9 B         6         0 B    
10 B         2         1 B1   
11 B         7         0 B2   
12 B        10         1 B3   
13 B         0         0 B4   
14 B         6         0 B4  
0 голосов
/ 22 февраля 2019

Та же идея, что и у @akrun, но с использованием только data.table

library(data.table)
setDT(df)

df[, newID := paste0(ID, gsub('^0$', '', rleid(condition) - 1)), ID]
df
#     ID value condition newID
#  1:  A     0         0     A
#  2:  A     3         0     A
#  3:  A     0         1    A1
#  4:  A     7         1    A1
#  5:  A     5         0    A2
#  6:  A     5         0    A2
#  7:  A     5         0    A2
#  8:  A     7         0    A2
#  9:  B     6         0     B
# 10:  B     2         1    B1
# 11:  B     7         0    B2
# 12:  B    10         1    B3
# 13:  B     0         0    B4
# 14:  B     6         0    B4
0 голосов
/ 22 февраля 2019

Одна опция после группировки по 'ID', создайте индекс с помощью rleid (из data.table) и измените его на paste 'ID' на основе условия с case_when

library(dplyr)
library(data.table)
df1 %>% 
   group_by(ID) %>%
   mutate(newID = rleid(condition)-1,
          newID = case_when(newID == 0 ~ first(ID), TRUE ~ paste0(first(ID), newID)))
# A tibble: 14 x 4
# Groups:   ID [2]
#   ID    value condition newID
#   <chr> <int>     <int> <chr>
# 1 A         0         0 A    
# 2 A         3         0 A    
# 3 A         0         1 A1   
# 4 A         7         1 A1   
# 5 A         5         0 A2   
# 6 A         5         0 A2   
# 7 A         5         0 A2   
# 8 A         7         0 A2   
# 9 B         6         0 B    
#10 B         2         1 B1   
#11 B         7         0 B2   
#12 B        10         1 B3   
#13 B         0         0 B4   
#14 B         6         0 B4   

данные

df1 <- structure(list(ID = c("A", "A", "A", "A", "A", "A", "A", "A", 
 "B", "B", "B", "B", "B", "B"), value = c(0L, 3L, 0L, 7L, 5L, 
 5L, 5L, 7L, 6L, 2L, 7L, 10L, 0L, 6L), condition = c(0L, 0L, 1L, 
 1L, 0L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L)), class = "data.frame", 
 row.names = c(NA, -14L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...