Comment supprimer des lignes dans un bloc de données?

224

J'ai un bloc de données nommé "mes données" qui ressemble à ceci:

   A  B  C   D 
1. 5  4  4   4 
2. 5  4  4   4 
3. 5  4  4   4 
4. 5  4  4   4 
5. 5  4  4   4 
6. 5  4  4   4 
7. 5  4  4   4 

Je voudrais supprimer la ligne 2,4,6. Par exemple, comme ceci:

   A  B  C   D
1. 5  4  4  4 
3. 5  4  4  4 
5. 5  4  4  4 
7. 5  4  4  4 
R newbie
la source
12
En outre, vous souhaiterez peut-être vous familiariser avec une terminologie courante pour travailler avec des données. Cela est généralement appelé subsetting, qui, si vous avez recherché dans Google pour « r sous - ensemble trame de données » vous obtiendriez la très utile UCLA R page FAQ . Bienvenue à Stackoverflow, au fait!
A5C1D2H2I1M1N2O1R2T1
Ajout de quelques moyens supplémentaires de sous-ensemble à l'aide de vecteurs booléens, en plus de l'excellente réponse de @ mrdwab.
Paul Hiemstra
2
@ A5C1D2H2I1M1N2O1R2T1: la FAQ UCLA pour le sous-ensemble R a été déplacée. Maintenant, c'est ici .
Mike Sherrill 'Cat Recall'

Réponses:

340

L'idée clé est de former un ensemble de lignes que vous souhaitez supprimer et de conserver le complément de cet ensemble.

Dans R, le complément d'un ensemble est donné par l'opérateur '-'.

Donc, en supposant que le data.frames'appelle myData:

myData[-c(2, 4, 6), ]   # notice the -

Bien sûr, n'oubliez pas de "réaffecter" myDatasi vous souhaitez supprimer entièrement ces lignes --- sinon, R imprime simplement les résultats.

myData <- myData[-c(2, 4, 6), ]
A5C1D2H2I1M1N2O1R2T1
la source
59
N'oubliez pas de noter le ,dedans! ;)
Steven Jeuris
5
que faire si votre trame de données n'est qu'une seule colonne. Il semble supprimer toute la structure et génère un vecteur des valeurs
road_to_quantdom
6
@road_to_quantdom, ajoutez- drop = FALSEy un.
A5C1D2H2I1M1N2O1R2T1
4
"Dans R, le complément d'un ensemble est donné par l'opérateur '-'" -> C'est une formulation très trompeuse. Les indices négatifs sont supprimés et c'est tout, il n'y a pas de notion de complément. Si vous travaillez avec logique et essayez de l'utiliser, -cela ne fonctionnera pas, car l'opérateur complémentaire pour les logiques est !. Le complément de c (2,4,6) dans les rangées serait plutôt setdiff (c (2,4,6), 1: nrow (myData)), qui n'est pas c (-2, -4, -6) , bien que les deux produisent les mêmes lignes lorsqu'ils sont utilisés avec [.
asac
2
@Speldosa, myData[-c(2, 4, 6),,drop=F]. En fait, je suggère que vous insériez toujours ,drop=Fjuste avant le ]dans n'importe quel accès matriciel.
Aaron McDaid
82

Vous pouvez également travailler avec un soi-disant vecteur booléen, alias logical:

row_to_keep = c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE)
myData = myData[row_to_keep,]

Notez que l' !opérateur agit comme un NOT, c'est !TRUE == FALSE-à- dire :

myData = myData[!row_to_keep,]

Cela semble un peu lourd par rapport à la réponse de @ mrwab (+1 btw :)), mais un vecteur logique peut être généré à la volée, par exemple lorsqu'une valeur de colonne dépasse une certaine valeur:

myData = myData[myData$A > 4,]
myData = myData[!myData$A > 4,] # equal to myData[myData$A <= 4,]

Vous pouvez transformer un vecteur booléen en un vecteur d'indices:

row_to_keep = which(myData$A > 4)

Enfin, une astuce très intéressante est que vous pouvez utiliser ce type de sous-ensemble non seulement pour l'extraction, mais aussi pour l'affectation:

myData$A[myData$A > 4,] <- NA

où la colonne Aest attribuée NA(pas un nombre) où Adépasse 4.

Paul Hiemstra
la source
Et si vous voulez les exclure? Dans votre exemple numéro 3, si vous décroissez
GabrielMontenegro
61

Problèmes de suppression par numéro de ligne

Pour des analyses rapides et sales, vous pouvez supprimer des lignes d'un data.frame par numéro selon la première réponse. C'est à dire,

newdata <- myData[-c(2, 4, 6), ] 

Cependant, si vous essayez d'écrire un script d'analyse de données robuste, vous devez généralement éviter de supprimer des lignes par position numérique. En effet, l'ordre des lignes de vos données peut changer à l'avenir. Un principe général d'une table data.frame ou d'une table de base de données est que l'ordre des lignes ne devrait pas avoir d'importance. Si l'ordre importe, cela doit être encodé dans une variable réelle dans le data.frame.

Par exemple, imaginez que vous avez importé un jeu de données et supprimé des lignes par position numérique après avoir inspecté les données et identifié les numéros de ligne des lignes que vous souhaitez supprimer. Cependant, à un moment ultérieur, vous allez dans les données brutes et regardez autour de vous et réorganisez les données. Votre code de suppression de ligne supprimera désormais les lignes incorrectes et, pire encore, il est peu probable que des erreurs vous avertissent que cela s'est produit.

Meilleure stratégie

Une meilleure stratégie consiste à supprimer des lignes en fonction des propriétés substantielles et stables de la ligne. Par exemple, si vous aviez une idvariable de colonne qui identifie de manière unique chaque cas, vous pouvez l'utiliser.

newdata <- myData[ !(myData$id %in% c(2,4,6)), ]

D'autres fois, vous aurez un critère d'exclusion formel qui pourrait être spécifié et vous pourriez utiliser l'un des nombreux outils de sous-ensemble dans R pour exclure les cas basés sur cette règle.

Jeromy Anglim
la source
11

Créez une colonne id dans votre bloc de données ou utilisez n'importe quel nom de colonne pour identifier la ligne. L'utilisation de l'index n'est pas juste à supprimer.

Utilisez la subsetfonction pour créer un nouveau cadre.

updated_myData <- subset(myData, id!= 6)
print (updated_myData)

updated_myData <- subset(myData, id %in% c(1, 3, 5, 7))
print (updated_myData)
Paranthaman Ramakrishnan
la source
9

Par séquence simplifiée:

mydata[-(1:3 * 2), ]

Par séquence:

mydata[seq(1, nrow(mydata), by = 2) , ]

Par séquence négative:

mydata[-seq(2, nrow(mydata), by = 2) , ]

Ou si vous souhaitez sous-ensemble en sélectionnant des nombres impairs:

mydata[which(1:nrow(mydata) %% 2 == 1) , ]

Ou si vous souhaitez sous-ensemble en sélectionnant des nombres impairs, version 2:

mydata[which(1:nrow(mydata) %% 2 != 0) , ]

Ou si vous souhaitez sous-ensemble en filtrant les nombres pairs:

mydata[!which(1:nrow(mydata) %% 2 == 0) , ]

Ou si vous souhaitez sous-ensemble en filtrant les nombres pairs, la version 2:

mydata[!which(1:nrow(mydata) %% 2 != 1) , ]
Elías De La Rosa
la source
5

Supprimer Dan de employee.data - Pas besoin de gérer un nouveau data.frame.

employee.data <- subset(employee.data, name!="Dan")
SQLWolfe
la source
0

Voici une fonction rapide et sale pour supprimer une ligne par index.

removeRowByIndex <- function(x, row_index) {
  nr <- nrow(x)
  if (nr < row_index) {
    print('row_index exceeds number of rows')
  } else if (row_index == 1)
  {
    return(x[2:nr, ])
  } else if (row_index == nr) {
    return(x[1:(nr - 1), ])
  } else {
    return (x[c(1:(row_index - 1), (row_index + 1):nr), ])
  }
}

Son principal défaut est que l'argument row_index ne suit pas le modèle R d'être un vecteur de valeurs. Il peut y avoir d'autres problèmes car je n'ai passé que quelques minutes à l'écrire et à le tester, et je n'ai commencé à utiliser R qu'au cours des dernières semaines. Tous les commentaires et améliorations à ce sujet seraient les bienvenus!

Alan Carlyle
la source
0

Pour être complet, j'ajouterai que cela peut aussi être fait dplyren utilisant slice. L'avantage de l'utiliser est qu'il peut faire partie d'un flux de travail canalisé.

df <- df %>%
  .
  .
  slice(-c(2, 4, 6)) %>%
  .
  .

Bien sûr, vous pouvez également l'utiliser sans tuyaux.

df <- slice(df, -c(2, 4, 6))

Le format "non vectoriel", -c(2, 4, 6)signifie obtenir tout ce qui n'est pas aux lignes 2, 4 et 6. Pour un exemple utilisant une plage, disons que vous vouliez supprimer les 5 premières lignes, vous pourriez le faire slice(df, 6:n()). Pour plus d'exemples, consultez la documentation .

Ryan H.
la source