Wie lösche ich Zeilen in einem Datenrahmen?

224

Ich habe einen Datenrahmen mit dem Namen "mydata", der folgendermaßen aussieht:

   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 

Ich möchte Zeile 2,4,6 löschen. Zum Beispiel so:

   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 Neuling
quelle
12
Möglicherweise möchten Sie sich auch mit einer gängigen Terminologie für die Arbeit mit Daten vertraut machen. Dies wird normalerweise als Teilmenge bezeichnet. Wenn Sie in Google nach "r Teilmengen-Datenrahmen" suchen, gelangen Sie zur sehr hilfreichen UCLA R-FAQ-Seite . Willkommen übrigens bei Stackoverflow!
A5C1D2H2I1M1N2O1R2T1
Zusätzlich zu der hervorragenden Antwort von @ mrdwab wurden einige zusätzliche Möglichkeiten zur Teilmenge mit booleschen Vektoren hinzugefügt.
Paul Hiemstra
2
@ A5C1D2H2I1M1N2O1R2T1: Die UCLA-FAQ für die R-Teilmenge wurde verschoben. Jetzt ist es hier .
Mike Sherrill 'Cat Recall'

Antworten:

340

Die Schlüsselidee ist, dass Sie eine Menge der Zeilen bilden, die Sie entfernen möchten, und die Ergänzung dieser Menge beibehalten.

In R wird das Komplement einer Menge durch den Operator '-' angegeben.

Angenommen, das data.frameheißt myData:

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

Vergessen myDataSie natürlich nicht, "neu zuzuweisen", wenn Sie diese Zeilen vollständig löschen möchten - andernfalls druckt R nur die Ergebnisse.

myData <- myData[-c(2, 4, 6), ]
A5C1D2H2I1M1N2O1R2T1
quelle
59
Vergessen Sie nicht, das dort zu beachten ,! ;)
Steven Jeuris
5
Was ist, wenn Ihr Datenrahmen nur aus einer Spalte besteht? Es scheint die gesamte Struktur zu
löschen
6
@road_to_quantdom, füge drop = FALSEdort ein hinzu.
A5C1D2H2I1M1N2O1R2T1
4
"In R wird das Komplement einer Menge durch den Operator '-' angegeben" -> Dies ist eine sehr irreführende Formulierung. Negative Indizes werden entfernt und das wars, es gibt keine Vorstellung von Komplement. Wenn Sie mit logisch arbeiten und versuchen, -es zu verwenden, funktioniert es nicht, da der Komplementoperator für logisch ist !. Das Komplement von c (2,4,6) in den Zeilen wäre eher setdiff (c (2,4,6), 1: nrow (myData)), was nicht c (-2, -4, -6) ist. , obwohl beide bei Verwendung mit die gleichen Zeilen ergeben würden [.
Asac
2
@ Speldosa , myData[-c(2, 4, 6),,drop=F]. In der Tat würde ich vorschlagen, dass Sie immer ,drop=Fkurz vor dem ]in einem Matrixzugriff einfügen .
Aaron McDaid
82

Sie können auch mit einem sogenannten booleschen Vektor arbeiten, auch bekannt als logical:

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

Beachten Sie, dass der !Operator als NOT fungiert, dh !TRUE == FALSE:

myData = myData[!row_to_keep,]

Dies scheint im Vergleich zu @ mrwabs Antwort (+1 übrigens :)) etwas umständlich zu sein, aber ein logischer Vektor kann im laufenden Betrieb generiert werden, z. B. wenn ein Spaltenwert einen bestimmten Wert überschreitet:

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

Sie können einen booleschen Vektor in einen Vektor von Indizes umwandeln:

row_to_keep = which(myData$A > 4)

Ein sehr guter Trick ist schließlich, dass Sie diese Art der Teilmenge nicht nur zum Extrahieren, sondern auch zum Zuweisen verwenden können:

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

Dabei wird eine Spalte Azugewiesen NA(keine Nummer), wobei A4 überschritten wird.

Paul Hiemstra
quelle
Was ist, wenn Sie sie ausschließen möchten? In Ihrem Beispiel Nummer 3, wenn Sie abnehmen
GabrielMontenegro
61

Probleme beim Löschen nach Zeilennummer

Für schnelle und schmutzige Analysen können Sie Zeilen eines data.frame nach Nummer gemäß der oberen Antwort löschen. Dh

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

Wenn Sie jedoch versuchen, ein robustes Datenanalyseskript zu schreiben, sollten Sie generell vermeiden, Zeilen nach numerischer Position zu löschen. Dies liegt daran, dass sich die Reihenfolge der Zeilen in Ihren Daten in Zukunft ändern kann. Ein allgemeines Prinzip eines data.frame oder einer Datenbanktabelle ist, dass die Reihenfolge der Zeilen keine Rolle spielen sollte. Wenn die Reihenfolge von Bedeutung ist, sollte dies in einer tatsächlichen Variablen im data.frame codiert werden.

Stellen Sie sich beispielsweise vor, Sie haben ein Dataset importiert und Zeilen nach numerischer Position gelöscht, nachdem Sie die Daten überprüft und die Zeilennummern der Zeilen identifiziert haben, die Sie löschen möchten. Zu einem späteren Zeitpunkt gehen Sie jedoch in die Rohdaten und sehen sich um und ordnen die Daten neu. Ihr Zeilenlöschcode löscht jetzt die falschen Zeilen. Schlimmer noch, es ist unwahrscheinlich, dass Sie Fehler erhalten, die Sie darauf hinweisen.

Bessere Strategie

Eine bessere Strategie besteht darin, Zeilen basierend auf inhaltlichen und stabilen Eigenschaften der Zeile zu löschen. Wenn Sie beispielsweise eine idSpaltenvariable hatten, die jeden Fall eindeutig identifiziert, können Sie diese verwenden.

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

In anderen Fällen haben Sie ein formales Ausschlusskriterium, das angegeben werden kann, und Sie können eines der vielen Teilmengenwerkzeuge in R verwenden, um Fälle auszuschließen, die auf dieser Regel basieren.

Jeromy Anglim
quelle
11

Erstellen Sie eine ID-Spalte in Ihrem Datenrahmen oder verwenden Sie einen beliebigen Spaltennamen, um die Zeile zu identifizieren. Die Verwendung von Index ist nicht fair zu löschen.

Verwenden Sie die subsetFunktion, um einen neuen Rahmen zu erstellen.

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
quelle
9

Durch vereinfachte Reihenfolge:

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

Nach Reihenfolge:

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

Durch negative Reihenfolge:

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

Oder wenn Sie eine Teilmenge durch Auswahl ungerader Zahlen erstellen möchten:

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

Oder wenn Sie eine Teilmenge durch Auswahl ungerader Zahlen erstellen möchten, Version 2:

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

Oder wenn Sie eine Teilmenge durch Herausfiltern gerader Zahlen erstellen möchten:

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

Oder wenn Sie eine Teilmenge durch Herausfiltern gerader Zahlen erstellen möchten, Version 2:

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

Dan aus employee.data löschen - Es ist nicht erforderlich, einen neuen data.frame zu verwalten.

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

Hier ist eine schnelle und schmutzige Funktion zum Entfernen einer Zeile nach 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), ])
  }
}

Der Hauptfehler besteht darin, dass das Argument row_index nicht dem R-Muster folgt, ein Vektor von Werten zu sein. Es kann andere Probleme geben, da ich nur ein paar Minuten damit verbracht habe, es zu schreiben und zu testen, und erst in den letzten Wochen angefangen habe, R zu verwenden. Kommentare und Verbesserungen hierzu wären sehr willkommen!

Alan Carlyle
quelle
0

Der Vollständigkeit halber möchte ich hinzufügen, dass dies dplyrauch mit verwendet werden kann slice. Dies hat den Vorteil, dass es Teil eines Pipeline-Workflows sein kann.

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

Natürlich können Sie es auch ohne Rohre verwenden.

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

Das Format "kein Vektor" -c(2, 4, 6)bedeutet, dass Sie alles erhalten, was sich nicht in den Zeilen 2, 4 und 6 befindet. Wenn Sie beispielsweise einen Bereich verwenden, können Sie beispielsweise die ersten 5 Zeilen entfernen slice(df, 6:n()). Weitere Beispiele finden Sie in den Dokumenten .

Ryan H.
quelle