0
votes

Données de sous-ensemble basées sur une instruction conditionnelle

Je voudrais savoir s'il existe un moyen de combiner l'instruction ifelse et la fonction de filtre (dans le package dplyr) pour sous-ensemble une trame de données. Considérez les données

df<-data.frame(id=c(1,2,2,2,3),
            A=c(3,5,4,3,9),
           D1=c(0,1,1,0,0),
           D2=c(1,0,0,1,0))

Je veux supprimer les lignes suivant D2 = 1 ou D1 = D2 = 0 pour chaque id. La sortie attendue ressemblerait à

df<-data.frame(id=c(1,1,1,2,2,2,2,3,3),
            A=c(3,6,2,5,4,3,8,9,8),
           D1=c(0,0,0,1,1,0,0,0,0),
           D2=c(1,0,0,0,0,1,1,0,1))

J'ai abordé cela par plusieurs tentatives en utilisant group_by et la fonction de filtre mais il semble que des instructions conditionnelles soient nécessaires mais je trouve difficile de combiner ceux-ci avec la fonction de filtre. J'ai rencontré plusieurs questions / réponses sur les données de sous-ensembles (par exemple, Comment sous-regrouper les données en filtrant et regroupant efficacement dans R ) mais celles-ci ne répondent pas à ma question. J'apprécie grandement toute aide à ce sujet.


1 commentaires

L'une des réponses répond-elle à votre question, TRichard? Si tel est le cas, veuillez en accepter un. Merci!


3 Réponses :


1
votes

Dans dplyr , vous pouvez trouver le premier index où la condition est remplie et sélectionner les lignes qui se produisent avant que la condition ne soit satisfaite pour chaque groupe.

df %>%
  group_by(id) %>%
  slice({
     inds <- which(D1 == 0 & D2 == 0 | D2 == 1)[1]
     if(!is.na(inds)) -((inds + 1):n()) else seq_len(n())})

Ce qui précède fonctionne en supposant qu'au moins une ligne dans chaque groupe satisfait à la condition. Un cas général, où il peut y avoir des instances où aucune des lignes ne satisfait la condition et que nous voulons sélectionner toutes les lignes du groupe que nous pouvons utiliser:

library(dplyr)
df %>%
  group_by(id) %>%
  filter(row_number() <= which(D1 == 0 & D2 == 0 | D2 == 1)[1])


#     id     A    D1    D2
#  <dbl> <dbl> <dbl> <dbl>
#1     1     3     0     1
#2     2     5     1     0
#3     2     4     1     0
#4     2     3     0     1
#5     3     9     0     0


0 commentaires

1
votes

Il ne semble pas que vous ayez besoin d'utiliser dplyr ici (sauf si je manque quelque chose). Essayez ceci:

df<-data.frame(id=c(1,1,1,2,2,2,2,3,3),
               A=c(3,6,2,5,4,3,8,9,8),
               D1=c(0,0,0,1,1,0,0,0,0),
               D2=c(1,0,0,0,0,1,1,0,1))

del = c()

for (i in 1:nrow(df)){
  if (df$D2[i] == 1 | (df$D1[i] ==0 & df$D2[i] == 0)){
    del = c(del, i)
  }
}

df = df[del,]


0 commentaires

0
votes

Pure dplyr :

df %>%
  group_by(id) %>%
  filter(row_number() == n() | rev(cumany(rev(!(D2 == 1 | (D1 == D2 & D2 == 0))))))
# # A tibble: 5 x 4
# # Groups:   id [3]
#      id     A    D1    D2
#   <dbl> <dbl> <dbl> <dbl>
# 1     1     2     0     0
# 2     2     5     1     0
# 3     2     4     1     0
# 4     2     8     0     1
# 5     3     8     0     1


0 commentaires