Использование dplyr для суммирования с условиями

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

df <- data.frame(c(1,1,1,2,2,2,3,3,3), as.logical(c(TRUE,FALSE,TRUE,TRUE,TRUE,TRUE,FALSE,TRUE,FALSE)),
                 as.numeric(c(0,5,0,0,0,0,7,0,7)))
colnames(df) <- c("ID", "Status", "Price")

  ID Status Price
1  1   TRUE     0
2  1  FALSE     5
3  1   TRUE     0
4  2   TRUE     0
5  2   TRUE     0
6  2   TRUE     0
7  3  FALSE     7
8  3   TRUE     0
9  3  FALSE     7

Я хотел бы отсортировать таблицу по наблюдению и получить статус ИСТИНА, только если все три наблюдения ИСТИННЫ (выяснены), а затем хочу получить цену, соответствующую статусу (т.е. 5 для наблюдения 1 как ЛОЖЬ, 0 для наблюдения 2 как ИСТИНА и 7 для наблюдения 3 как ЛОЖЬ).

Из Суммировать с условиями в dplyr я понял, что могу - как обычно - укажите условия в квадратных скобках. Мой код до сих пор выглядит так:

library(dplyr)
result <- df %>%
  group_by(ID) %>%
  summarize(Status = all(Status), Test = ifelse(all(Status) == TRUE,
 first(Price[Status == TRUE]), first(Price[Status == FALSE]))) 

# This is what I get: 
# A tibble: 3 x 3
     ID Status  Test
  <dbl> <lgl>  <dbl>
1    1. FALSE     0.
2    2. TRUE      0.
3    3. FALSE     7.

Но, как видите, для ID = 1 он дает неверную цену. Я пробовал это вечно, поэтому был бы признателен за любой намек относительно того, где я ошибся.


person WillyWonka    schedule 22.02.2019    source источник


Ответы (2)


Мы могли бы сохранить all(Status) в качестве второго аргумента в summarise (или изменить имя столбца), а также, это можно сделать с помощью if/else, поскольку логика, кажется, возвращает одно ИСТИНА / ЛОЖЬ в зависимости от того, является ли all из «Статус» ИСТИНА или нет.

df %>%
   group_by(ID) %>% 
   summarise( Test = if(all(Status)) first(Price[Status]) else 
                   first(Price[!Status]), Status = all(Status))
# A tibble: 3 x 3
#     ID  Test Status
#   <dbl> <dbl> <lgl> 
#1     1     5 FALSE 
#2     2     0 TRUE  
#3     3     7 FALSE 

ПРИМЕЧАНИЕ. Лучше не использовать ifelse с разными длинами аргументов.

person akrun    schedule 22.02.2019

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

df %>%
  group_by(ID) %>%
  mutate(status = Status) %>%
  summarise(
    Status = all(Status),
    Test = ifelse(Status == TRUE,
                  first(Price),
                  first(Price[status == FALSE]))
  )

Выход:

# A tibble: 3 x 3
     ID Status  Test
  <dbl> <lgl>  <dbl>
1     1 FALSE      5
2     2 TRUE       0
3     3 FALSE      7

Проблема в том, что вы хотите использовать Status для Test столбца, когда вы уже изменили его, чтобы он больше не содержал исходных значений.

Сделайте копию раньше (я сохранил ее в status), выполните для нее ifelse, и она будет работать нормально.

person arg0naut91    schedule 22.02.2019