Используйте group_by и case_when, чтобы получить одно значение для группы - PullRequest
3 голосов
/ 24 марта 2020

У меня есть data.frame с id и stage. stage является символом, но соответствует упорядоченному процессу (A -> B -> C -> ...).

expand.grid(id=c(1:5), stage = LETTERS[1:4]) %>%
 arrange(id) %>%
 mutate(flag = case_when(str_detect(stage, "D") ~ "Dance",
                         str_detect(stage, "C") ~ "Climb",
                         str_detect(stage, "B") ~ "Biceps",
                         str_detect(stage, "A") ~ "Aerobic"))

Это производит то, что я ожидал, векторизованный флаг case для case колонка. Но я хочу, чтобы вывод моего case_when был уникальным для всей группы id. Поэтому я попытался добавить group_by(id)

expand.grid(id=c(1:5), stage = LETTERS[1:4]) %>%
 arrange(id) %>%
 group_by(id) %>%
 mutate(flag = case_when(str_detect(stage, "D") ~ "Dance",
                         str_detect(stage, "C") ~ "Climb",
                         str_detect(stage, "B") ~ "Biceps",
                         str_detect(stage, "A") ~ "Aerobic"))

Но это не меняет природу результата. Изменение mutate на summarize не дает эффекта суммирования, на который я надеялся. Вполне вероятно, что я не полностью понимаю функционирование case_when() и group_by(), и поэтому я не могу написать правильную команду, чтобы получить сводную информацию, которую я ищу.

Мой ожидаемый результат id, stage должны быть последним этапом заказа и flag в соответствии с этим этапом.

     id stage flag 
  <int> <fct> <chr>
1     1 D     Dance
2     2 D     Dance
3     3 D     Dance
4     4 D     Dance
5     5 D     Dance

Для большей ясности предположим, что id 1 и 2 находятся на стадии A, 3 на B, 4 на C и 5 на D.

toy <- expand.grid(id=c(1:5), stage = LETTERS[1:4]) %>%
 arrange(id) %>%
 group_by(id) %>%
 mutate(flag = case_when(str_detect(stage, "D") ~ "Dance",
                         str_detect(stage, "C") ~ "Climb",
                         str_detect(stage, "B") ~ "Biceps",
                         str_detect(stage, "A") ~ "Aerobic"))
# grabbing only some of them
toy <- toy[c(1, 5, 10, 15, 20),]

Вывод должен выглядеть следующим образом:

     id stage flag   
  <int> <fct> <chr>  
1     1 A     Aerobic
2     2 A     Aerobic
3     3 B     Biceps 
4     4 C     Climb  
5     5 D     Dance

Я в порядке с повторным id, я могу подвести итог оттуда.

1 Ответ

3 голосов
/ 24 марта 2020

Вы можете использовать any (и порядок операций в case_when, чтобы получить flag, который вы хотите, в пределах summarize. Нам нужно добавить немного, чтобы сохранить stage.

expand.grid(id=c(1:5), stage = LETTERS[1:4]) %>%
  arrange(id) %>%
  group_by(id) %>%
  summarize(
   stage = intersect(c("D","C","B","A"), stage)[1],
   flag = case_when(any(str_detect(stage, "D")) ~ "Dance",
                    any(str_detect(stage, "C")) ~ "Climb",
                    any(str_detect(stage, "B")) ~ "Biceps",
                    any(str_detect(stage, "A")) ~ "Aerobic")
  )
# # A tibble: 5 x 3
#      id stage flag 
#   <int> <chr> <chr>
# 1     1 D     Dance
# 2     2 D     Dance
# 3     3 D     Dance
# 4     4 D     Dance
# 5     5 D     Dance

Однако, альтернатива, использующая left_join, которая позволяет избежать кусочной операции case_when.

acronyms <- data.frame(
  prio  = 1:4,
  stage = c("D", "C", "B", "A"),
  flag  = c("Dance", "Climb", "Biceps", "Aerobic")
)

expand.grid(id=c(1:5), stage = LETTERS[1:4]) %>%
  left_join(acronyms) %>%
  arrange(id, prio) %>%
  group_by(id) %>%
  slice(1) %>%
  select(-prio) %>%
  ungroup()

Основа c stage / flag ассоциация в acronyms в основном достаточно; я добавил prio для определения c и простой способ всегда получать самые важные для каждого id. Здесь могут быть другие полезные приемы в зависимости от вашей конечной потребности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...