удалить строки, если заявления - PullRequest
0 голосов
/ 17 сентября 2018

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

Status  ID 
  A     1
  B     1
  B     1
  A     1
  B     1
  A     1
  A     2
  A     2
  A     2
  A     2
  B     3
  B     3
  B     3

Чтобы проиллюстрировать мой желаемый результат, пожалуйста, посмотрите ниже:

Status  ID 
  B     1
  B     1
  B     1
  A     2
  A     2
  A     2
  A     2
  B     3
  B     3
  B     3

Как видите,Единственное, что меняется, это для группы с идентификатором = 1. Если группа содержит статус «A» и «B», я бы хотела удалить статус «A».

Однако идентификатор группы 2 и3 не изменился (т.е. не было удалено ни одной строки), потому что: если каждый идентификатор группы содержит только «A», то он останется прежним.Аналогичным образом, если каждый идентификатор группы содержит только «B», он также останется прежним.Следовательно, оба остаются неизменными.

Используя dplyr, это моя попытка:

library(dplyr)

df1_clean <- df1 %>% group_by(ID, Status)
                 %>% filter(ifelse((Status == A | Status == B), Status == B,
                     ifelse((Status == A), Status == A,
                     ifelse((Status == B), Status == B))))

Однако этот фильтр не будет работать.Любая помощь будет оценена!

Ответы [ 2 ]

0 голосов
/ 17 сентября 2018

Прежде всего, всегда желательно привести пример в удобном для копирования формате, используя dput(df1), чтобы другие могли легко восстановить данные.

Эта задача может быть достигнута путем создания столбца флага, который указывает, имеет ли ID несколько Status или нет, и затем фильтрует те, которые не имеют несколько status или status == "B". Следующим образом:

clean_df1 <- df1 %>%
  group_by(ID) %>%
  mutate(multiple = if_else(n_distinct(Status) > 1, TRUE, FALSE)) %>%
  filter(!multiple | Status == "B") %>%
  ungroup() %>% select(- multiple)
# A tibble: 10 x 2
   Status    ID
   <fct>  <dbl>
 1 B          1
 2 B          1
 3 B          1
 4 A          2
 5 A          2
 6 A          2
 7 A          2
 8 B          3
 9 B          3
10 B          3
0 голосов
/ 17 сентября 2018

Мы можем использовать filter, сгруппированные по ID

library(dplyr)
df %>%
  group_by(ID) %>%
  filter(all(Status == "A") | all(Status == "B") | Status == "B")

#   Status    ID
#   <fct>  <int>
# 1 B          1
# 2 B          1
# 3 B          1
# 4 A          2
# 5 A          2
# 6 A          2
# 7 A          2
# 8 B          3
# 9 B          3
#10 B          3

Мы также можем использовать n_distinct

df %>%
  group_by(ID) %>%
  filter(n_distinct(Status) == 1 | Status == "B")

Эквивалентная базовая версия R ave версии будет

df[as.logical(with(df, ave(Status, ID, FUN = function(x) 
          all(x == "A") | all(x == "B") | x == "B"))), ]

df[as.logical(with(df, ave(Status, ID, FUN = function(x) 
         length(unique(x)) == 1 | x == "B"))), ]
...