web-dev-qa-db-fra.com

Supprimer des lignes en fonction de plusieurs conditions avec dplyr

J'essaie de supprimer des lignes spécifiques dans mon ensemble de données en fonction des valeurs de plusieurs colonnes. Une ligne ne doit être supprimée que lorsqu'une condition des 3 colonnes est remplie. 

Ceci est mon code:

test_dff %>%
  filter(contbr_nm != c('GAITHER, BARBARA', 'PANIC, RADIVOJE', 'KHAN, RAMYA') & 
           contbr_city != c('APO AE', 'PORSGRUNN', 'NEW YORK') &
           contbr_Zip != c('9309', '3924', '2586'))

Ce code devrait supprimer 12 lignes de ma table. Au lieu de cela, il en supprime une grande majorité. Je soupçonne qu’il supprime toutes les lignes possibles chaque fois que l’une des conditions est remplie. 

Existe-t-il une meilleure solution ou dois-je utiliser l'approche décrite ici ?

Dois-je spécifier chaque combinaison séparément? Ainsi? Cette approche supprime également beaucoup trop de lignes, elle est donc également incorrecte.

test_dff %>%
  filter((contbr_nm != 'GAITHER, BARBARA' & contbr_city != 'APO AE' & contbr_Zip != '9309') &
         (contbr_nm != 'PANIC, RADIVOJE' & contbr_city != 'PORSGRUNN' & contbr_Zip != '3924') &
           (contbr_nm != 'KHAN, RAMYA' & contbr_city != 'NEW YORK' & contbr_Zip != '2586') )

Si je me concentre sur la suppression de lignes basées sur une seule variable, ce code fonctionne:

test_dff %>%
  filter(contbr_Zip != c('9309')) %>%
  filter(contbr_Zip != c('3924')) %>%
  filter(contbr_Zip != c('2586'))

Pourquoi une telle approche ne fonctionne-t-elle pas?

test_dff %>%
  filter(contbr_Zip != c('9309','3924','2586')) 

Merci beaucoup pour votre aide.

3
Trgovec

Voici une approche basée sur les jointures - tous les éléments doivent correspondre exactement.

main <- read.csv(text = "
id,name,city,Zip
1,mary,new york,10017
2,jonah,new york,10016
3,tamil,manhattan,10019
4,vijay,harlem,10028
")

excludes <- read.csv(text = "
name,city,Zip
jonah,new york,10016
vijay,harlem,10028
")

library(dplyr)
anti_join(main, excludes)

#   id  name      city   Zip
# 1  3 tamil manhattan 10019
# 2  1  mary  new york 10017
3
Andrew Lavers

Ajuster votre deuxième question (non testé)

test_dff %>%
  filter(!((contbr_nm == 'GAITHER, BARBARA' & contbr_city == 'APO AE' & contbr_Zip == '9309') |
           (contbr_nm == 'PANIC, RADIVOJE' & contbr_city == 'PORSGRUNN' & contbr_Zip == '3924') |
           (contbr_nm == 'KHAN, RAMYA' & contbr_city == 'NEW YORK' & contbr_Zip == '2586') ))
3
Andrew Lavers

Voici une approche qui crée une nouvelle variable en concaténant les valeurs dans les multiples colonnes que vous souhaitez référencer avec votre filtre:

set.seed(15)
dfTest <- data.frame(matrix(round(rnorm(20),3), nrow=10))
dfTest$tempcol <- paste(dfTest$X1,dfTest$X2)

head(dfTest)
      X1     X2       tempcol
1  0.259  0.855   0.259 0.855
2  1.831 -0.365  1.831 -0.365
3 -0.340  0.166   -0.34 0.166
4  0.897 -1.243  0.897 -1.243
5  0.488  1.459   0.488 1.459
6 -1.255 -0.004 -1.255 -0.004

#Now remove the values by filtering on tempcol
dfTest %>%
  filter(tempcol != '0.259 0.855') %>%
  select(1:2) #omit tempcol in output

      X1     X2
1  1.831 -0.365
2 -0.340  0.166
3  0.897 -1.243
4  0.488  1.459
5 -1.255 -0.004
6  0.023 -0.021
7  1.091  0.032
8 -0.132 -1.167
9 -1.075 -0.520
0
Chris K