Сохранять строки до первого появления значения в столбце по группам. Группы без значения разрешены

У меня есть такой фрейм данных:

> df
  id type
1  1    a
2  1    a
3  1    b
4  1    a
5  1    b
6  2    a
7  2    a
8  2    b
9  3    a
10 3    a

Я хочу сохранить все строки для каждой группы (id) до первого появления значения «b» в столбце типа. Для групп без типа «b» я хочу сохранить все их строки.

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

> dfnew
  id type
1  1    a
2  1    a
3  1    b
4  2    a
5  2    a
6  2    b
7  3    a
8  3    a

Я пробовал следующий код, но он сохраняет дополнительные строки, которые имеют значение «a» после первого появления «b», и исключает только дополнительные вхождения «b», чего я не хочу. Посмотрите на строку 4 ниже. Я хочу избавиться от этого.

> df %>% group_by(id) %>% filter(cumsum(type == 'b') <= 1)
Source: local data frame [7 x 2]
Groups: id

  id type
1  1    a
2  1    a
3  1    b
4  1    a
5  2    a
6  2    a
7  2    b
8  3    a
9  3    a

person Gopala    schedule 30.07.2015    source источник


Ответы (1)


Вы можете комбинировать match или which с slice или (как упомянул @Richard) which.max

library(dplyr)
df %>% 
  group_by(id) %>% 
  slice(if(any(type == "b")) 1:which.max(type == "b") else row_number())    
# Source: local data table [8 x 2]
# Groups: id
# 
#   id type
# 1  1    a
# 2  1    a
# 3  1    b
# 4  2    a
# 5  2    a
# 6  2    b
# 7  3    a
# 8  3    a

Или вы можете попробовать это с data.table

library(data.table)
setDT(df)[, if(any(type == "b")) .SD[1:which.max(type == "b")] else .SD, by = id]
#    id type
# 1:  1    a
# 2:  1    a
# 3:  1    b
# 4:  2    a
# 5:  2    a
# 6:  2    b
# 7:  3    a
# 8:  3    a
person David Arenburg    schedule 30.07.2015
comment
Или просто which.max() - person Rich Scriven; 31.07.2015
comment
Я получаю эту ошибку в моем фрейме данных: Ошибка: аргумент NA / NaN. Причина, по которой я считаю, заключается в том, что не все "группы" имеют тип == "b". - person Gopala; 31.07.2015
comment
Вы не получите эту ошибку с slice(1:which.max(type == "b")), хотя каков ваш желаемый результат в таком случае? - person David Arenburg; 31.07.2015
comment
Я изменил свой вопрос на основе этого варианта использования и желаемого результата. Команда, которую я использовал, правильно обработала этот случай, но не исключила строки, возникающие после того, как встречается тип 'b'. Я попробую which.max (). - person Gopala; 31.07.2015
comment
Хорошо, посмотрите мои изменения и другое решение с использованием data.table - person David Arenburg; 31.07.2015