Jak usunąć wiersze w ramce danych?

224

Mam ramkę danych o nazwie „mydata”, która wygląda następująco:

   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 

Chciałbym usunąć wiersz 2,4,6. Na przykład:

   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 nowicjusz
źródło
12
Możesz także zapoznać się z pewną powszechną terminologią dotyczącą pracy z danymi. Zazwyczaj jest to określane jako podzbioru, który, jeśli wyszukiwane w Google dla „R podzbiór danych ramce” będzie można dostać się do bardzo pomocny UCLA R FAQ stronie . Nawiasem mówiąc, witamy w Stackoverflow!
A5C1D2H2I1M1N2O1R2T1
Dodano kilka dodatkowych sposobów podzbiorów za pomocą wektorów boolowskich, oprócz doskonałej odpowiedzi @ mrdwab.
Paul Hiemstra
2
@ A5C1D2H2I1M1N2O1R2T1: Przeniesiono FAQ UCLA dla podzbiorów R. Teraz jest tutaj .
Mike Sherrill „Cat Recall”

Odpowiedzi:

340

Kluczową ideą jest utworzenie zestawu wierszy, które chcesz usunąć, i zachowanie uzupełnienia tego zestawu.

W R uzupełnienie zbioru jest podawane przez operator „-”.

Zakładając, że data.framenazywa się to myData:

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

Oczywiście nie zapomnij o „ponownym przypisaniu”, myDatajeśli chcesz całkowicie upuścić te wiersze --- w przeciwnym razie R po prostu drukuje wyniki.

myData <- myData[-c(2, 4, 6), ]
A5C1D2H2I1M1N2O1R2T1
źródło
59
Nie zapomnij zanotować ,tam! ;)
Steven Jeuris
5
co jeśli twoja ramka danych to tylko jedna kolumna. Wydaje się, że upuszcza całą strukturę i generuje wektor wartości
road_to_quantdom
6
@road_to_quantdom, dodaj drop = FALSEtam.
A5C1D2H2I1M1N2O1R2T1
4
„W języku R uzupełnienie zbioru jest podane przez operator„ - ”. -> Jest to bardzo mylące sformułowanie. Indeksy ujemne są usuwane i to wszystko, nie ma pojęcia uzupełnienia. Jeśli pracujesz z logiką i spróbujesz -jej użyć, to nie zadziała, ponieważ operatorem dopełniającym dla logiki jest !. Uzupełnienie c (2,4,6) w wierszach byłoby raczej ustawione na różnicę (c (2,4,6), 1: nrow (myData)), która nie jest c (-2, -4, -6) , chociaż oba przyniosłyby te same wiersze, gdy były używane z [.
asac
2
@Speldosa, myData[-c(2, 4, 6),,drop=F]. W rzeczywistości sugerowałbym, aby zawsze wstawiać ,drop=Ftuż przed ]dostępem do macierzy.
Aaron McDaid
82

Możesz także pracować z tak zwanym wektorem boolowskim, czyli logical:

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

Zauważ, że !operator działa jako NIE, tzn . !TRUE == FALSE:

myData = myData[!row_to_keep,]

To wydaje się nieco kłopotliwe w porównaniu z odpowiedzią @ mrwab (+1 btw :)), ale wektor logiczny można wygenerować w locie, np. Gdy wartość kolumny przekracza pewną wartość:

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

Możesz przekształcić wektor boolowski w wektor indeksów:

row_to_keep = which(myData$A > 4)

Wreszcie, bardzo fajną sztuczką jest to, że możesz użyć tego rodzaju podzestawu nie tylko do ekstrakcji, ale także do przypisania:

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

gdzie kolumna Ajest przypisana NA(nie liczba), gdzie Aprzekracza 4.

Paul Hiemstra
źródło
Co jeśli chcesz je wykluczyć? W twoim przykładzie numer 3, jeśli zanikniesz
Gabriel Czarnogóra
61

Problemy z usuwaniem według numeru wiersza

W celu szybkich i brudnych analiz można usunąć wiersze data.frame według numeru, zgodnie z pierwszą odpowiedzią. To znaczy,

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

Jeśli jednak próbujesz napisać solidny skrypt analizy danych, na ogół powinieneś unikać usuwania wierszy według pozycji liczbowej. Wynika to z faktu, że kolejność wierszy danych może ulec zmianie w przyszłości. Ogólna zasada tabel data.frame lub baz danych polega na tym, że kolejność wierszy nie powinna mieć znaczenia. Jeśli kolejność ma znaczenie, należy ją zakodować w zmiennej rzeczywistej w pliku data.frame.

Na przykład wyobraź sobie, że po sprawdzeniu danych i zidentyfikowaniu numerów wierszy, które chcesz usunąć, zaimportowałeś zestaw danych i usunąłeś wiersze według pozycji numerycznej. Jednak w pewnym momencie przechodzisz do surowych danych, rozglądasz się i porządkujesz dane. Twój kod usuwania wierszy usunie teraz nieprawidłowe wiersze, a co gorsza, prawdopodobnie nie pojawi się żaden błąd z ostrzeżeniem, że tak się stało.

Lepsza strategia

Lepszą strategią jest usuwanie wierszy na podstawie istotnych i stabilnych właściwości wiersza. Na przykład, jeśli masz idzmienną kolumnową, która jednoznacznie identyfikuje każdy przypadek, możesz tego użyć.

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

Innym razem będziesz mieć formalne kryteria wykluczenia, które można określić, i możesz użyć jednego z wielu narzędzi podziału w R, aby wykluczyć przypadki oparte na tej regule.

Jeromy Anglim
źródło
11

Utwórz kolumnę id w ramce danych lub użyj dowolnej nazwy kolumny, aby zidentyfikować wiersz. Używanie indeksu jest niesprawiedliwe do usunięcia.

Użyj subsetfunkcji, aby utworzyć nową ramkę.

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
źródło
9

W uproszczonej kolejności:

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

Po sekwencji:

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

W kolejności ujemnej:

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

Lub jeśli chcesz podzielić, wybierając liczby nieparzyste:

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

Lub jeśli chcesz podzielić, wybierając liczby nieparzyste, wersja 2:

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

Lub jeśli chcesz dokonać podzbioru, odfiltrowując liczby parzyste:

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

Lub jeśli chcesz podzielić, odfiltrowując liczby parzyste, wersja 2:

mydata[!which(1:nrow(mydata) %% 2 != 1) , ]
Elías De La Rosa
źródło
5

Usuń Dan z worker.data - Nie musisz zarządzać nową ramką data.frame.

employee.data <- subset(employee.data, name!="Dan")
SQLWolfe
źródło
0

Oto szybka i brudna funkcja usuwania wiersza według indeksu.

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), ])
  }
}

Jego główną wadą jest to, że argument row_index nie odpowiada wzorcowi R bycia wektorem wartości. Mogą występować inne problemy, ponieważ spędziłem tylko kilka minut na pisaniu i testowaniu, a zacząłem używać R w ciągu ostatnich kilku tygodni. Wszelkie uwagi i poprawki w tym zakresie byłyby mile widziane!

Alan Carlyle
źródło
0

Dla kompletności dodam, że można to zrobić dplyrrównież przy użyciu slice. Zaletą korzystania z tego jest to, że może on być częścią przepływu pracy w potoku.

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

Oczywiście możesz go również używać bez rur.

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

Format „nie wektorowy” -c(2, 4, 6)oznacza uzyskanie wszystkiego, czego nie ma w wierszach 2, 4 i 6. Na przykład przy użyciu zakresu, powiedzmy, że chcesz usunąć pierwsze 5 wierszy, możesz to zrobić slice(df, 6:n()). Aby uzyskać więcej przykładów, zobacz dokumenty .

Ryan H.
źródło