Păstrați rândurile până la prima apariție a unei valori într-o coloană, pe grup. Grupuri fără valoare permise

Am un cadru de date ca acesta:

> 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

Vreau să păstrez toate rândurile pentru fiecare grup (id) până la prima apariție a valorii „b” în coloana de tip. Pentru grupurile fără tipul „b”, vreau să păstrez toate rândurile lor.

Cadrul de date rezultat ar trebui să arate astfel:

> 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

Am încercat următorul cod, dar păstrează rânduri suplimentare care au valoarea „a” dincolo de prima apariție a lui „b” și exclude doar aparițiile suplimentare ale lui „b”, ceea ce nu este ceea ce vreau. Priviți rândul 4 din următoarele. Vreau să scap de el.

> 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 sursă


Răspunsuri (1)


Puteți combina match sau which cu slice sau (după cum a menționat @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

Sau poți încerca cu 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
Sau doar which.max() - person Rich Scriven; 31.07.2015
comment
Primesc această eroare pe cadrul meu de date: Eroare: argument NA/NaN. Motivul cred că nu toate „grupurile” au tipul == „b”. - person Gopala; 31.07.2015
comment
Nu veți primi acea eroare cu slice(1:which.max(type == "b")), deși care este rezultatul dorit în acest caz? - person David Arenburg; 31.07.2015
comment
Mi-am modificat întrebarea pe baza acestui caz de utilizare și a rezultatului dorit. Comanda pe care o foloseam a tratat corect acest caz, dar nu excluderea rândurilor care apar după ce tipul „b” este întâlnit. Voi încerca care.max(). - person Gopala; 31.07.2015
comment
Ok, vezi editarea mea și o altă soluție folosind data.table - person David Arenburg; 31.07.2015