web-dev-qa-db-fra.com

Suppression de lignes spécifiques d'une trame de données

J'ai une trame de données, par exemple:

sub   day
1      1
1      2
1      3
1      4
2      1
2      2
2      3
2      4
3      1
3      2
3      3
3      4

et je voudrais supprimer des lignes spécifiques qui peuvent être identifiées par la combinaison de sous et jour. Par exemple, disons que je voulais supprimer les lignes où sub = '1' et day = '2' et sub = 3 et day = '4'. Comment pourrais-je faire ça? Je me rends compte que je pourrais spécifier les numéros de ligne, mais cela doit être appliqué à une énorme trame de données qui serait fastidieuse à parcourir et à identifier chaque ligne.

24
RodgerDodger
DF[ ! ( ( DF$sub ==1 & DF$day==2) | ( DF$sub ==3 & DF$day==4) ) , ]   # note the ! (negation)

Ou si sub est un facteur comme le suggère votre utilisation de guillemets:

DF[ ! paste(sub,day,sep="_") %in% c("1_2", "3_4"), ]

Pourrait également utiliser un sous-ensemble:

subset(DF,  ! paste(sub,day,sep="_") %in% c("1_2", "3_4") )

(Et j'approuve l'utilisation de which dans la réponse de Dirk lors de l'utilisation de "[" même si certains prétendent que ce n'est pas nécessaire.)

35
42-

Cela se résume à deux étapes distinctes:

  1. Déterminez quand votre condition est vraie et calculez donc un vecteur de booléens, ou, comme je préfère, leurs indices en l'enveloppant dans which()
  2. Créez un data.frame en excluant les indices de l'étape précédente.

Voici un exemple:

R> set.seed(42)
R> DF <- data.frame(sub=rep(1:4, each=4), day=sample(1:4, 16, replace=TRUE))
R> DF
   sub day
1    1   4
2    1   4
3    1   2
4    1   4
5    2   3
6    2   3
7    2   3
8    2   1
9    3   3
10   3   3
11   3   2
12   3   3
13   4   4
14   4   2
15   4   2
16   4   4
R> ind <- which(with( DF, sub==2 & day==3 ))
R> ind
[1] 5 6 7
R> DF <- DF[ -ind, ]
R> table(DF)
   day
sub 1 2 3 4
  1 0 1 0 3
  2 1 0 0 0
  3 0 1 3 0
  4 0 2 0 2
R> 

Et nous voyons que sub==2 n'a plus qu'une entrée avec day==1.

Edit La condition composée peut être effectuée avec un 'ou' comme suit:

ind <- which(with( DF, (sub==1 & day==2) | (sub=3 & day=4) ))

et voici un nouvel exemple complet

R> set.seed(1)
R> DF <- data.frame(sub=rep(1:4, each=5), day=sample(1:4, 20, replace=TRUE))
R> table(DF)
   day
sub 1 2 3 4
  1 1 2 1 1
  2 1 0 2 2
  3 2 1 1 1
  4 0 2 1 2
R> ind <- which(with( DF, (sub==1 & day==2) | (sub==3 & day==4) ))
R> ind
[1]  1  2 15
R> DF <- DF[-ind, ]
R> table(DF)
   day
sub 1 2 3 4
  1 1 0 1 1
  2 1 0 2 2
  3 2 1 1 0
  4 0 2 1 2
R> 
16
Dirk Eddelbuettel

Voici une solution à votre problème en utilisant la fonction filter de dplyr .

Bien que vous puissiez passer votre bloc de données comme premier argument à n'importe quelle fonction dplyr, j'ai utilisé son %>%, qui canalise votre bloc de données vers une ou plusieurs fonctions dplyr (filtrez simplement dans ce cas).

Une fois que vous êtes un peu familier avec dplyr, le aide-mémoire est très pratique.

> print(df <- data.frame(sub=rep(1:3, each=4), day=1:4))
   sub day
1    1   1
2    1   2
3    1   3
4    1   4
5    2   1
6    2   2
7    2   3
8    2   4
9    3   1
10   3   2
11   3   3
12   3   4
> print(df <- df %>% filter(!((sub==1 & day==2) | (sub==3 & day==4))))
   sub day
1    1   1
2    1   3
3    1   4
4    2   1
5    2   2
6    2   3
7    2   4
8    3   1
9    3   2
10   3   3
9
Ken Lin

une solution simple

cond1 <- df$sub == 1 & df$day == 2

cond2 <- df$sub == 3 & df$day == 4

df <- df[!cond1,]

df <- df[!cond2,]

2
Ajay Choudhary