Come si eliminano le righe in un frame di dati?


224

Ho un frame di dati chiamato "mydata" che assomiglia a questo:

   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 

Vorrei cancellare la riga 2,4,6. Ad esempio, in questo modo:

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

12
Inoltre, potresti voler acquisire familiarità con una terminologia comune per lavorare con i dati. Questo di solito viene chiamato subsetting, che, se si cercasse in Google "frame di dati del sottoinsieme", si accede alla pagina UCLA R FAQ molto utile . Benvenuto su Stackoverflow, a proposito!
A5C1D2H2I1M1N2O1R2T1

Aggiunti alcuni modi aggiuntivi di sottoimpostazione usando vettori booleani, oltre all'eccellente risposta di @ mrdwab.
Paul Hiemstra,

2
@ A5C1D2H2I1M1N2O1R2T1: le domande frequenti UCLA per il subsetting R sono state spostate. Adesso è qui .
Mike Sherrill "Cat Recall",

Risposte:


340

L'idea chiave è formare un set di righe che si desidera rimuovere e mantenere il complemento di quel set.

In R, il complemento di un set è dato dall'operatore '-'.

Quindi, supponendo che data.framesi chiama myData:

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

Ovviamente, non dimenticare di "riassegnare" myDatase si desidera eliminare completamente quelle righe --- altrimenti, R stampa semplicemente i risultati.

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

59
Non dimenticare di annotare l'interno ,! ;)
Steven Jeuris il

5
cosa succede se il tuo frame di dati è solo una colonna. Sembra far cadere l'intera struttura e produce un vettore di valori
road_to_quantdom

6
@road_to_quantdom, aggiungi un drop = FALSElì.
A5C1D2H2I1M1N2O1R2T1

4
"In R, il complemento di un set è dato dall'operatore '-'" -> Questa è una formulazione molto fuorviante. Gli indici negativi vengono rimossi e basta, non c'è idea di complemento. Se lavori con la logica e provi a usarla -non funzionerà, perché l'operatore del complemento per la logica è !. Il complemento di c (2,4,6) nelle righe sarebbe piuttosto setdiff (c (2,4,6), 1: nrow (myData)), che non è c (-2, -4, -6) , anche se entrambi genererebbero le stesse righe se usati con [.
asac,

2
@Speldosa, myData[-c(2, 4, 6),,drop=F]. In effetti, suggerirei di inserire sempre ,drop=Fappena prima ]dell'accesso in qualsiasi matrice.
Aaron McDaid,

82

Puoi anche lavorare con un cosiddetto vettore booleano, ovvero logical:

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

Si noti che l' !operatore funge da NOT, ovvero !TRUE == FALSE:

myData = myData[!row_to_keep,]

Questo sembra un po 'complicato rispetto alla risposta di @ mrwab (+1 btw :)), ma un vettore logico può essere generato al volo, ad esempio dove un valore di colonna supera un certo valore:

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

Puoi trasformare un vettore booleano in un vettore di indici:

row_to_keep = which(myData$A > 4)

Infine, un trucco molto accurato è che puoi utilizzare questo tipo di sottoimpostazione non solo per l'estrazione, ma anche per l'assegnazione:

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

dove Aè assegnata la colonna NA(non un numero) dove Asupera 4.


E se si desidera escluderli? Nel tuo esempio numero 3, se stai
calando

61

Problemi con l'eliminazione per numero di riga

Per analisi rapide e sporche, è possibile eliminare le righe di un data.frame in base al numero secondo la risposta principale. Vale a dire,

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

Tuttavia, se si sta tentando di scrivere uno script di analisi dei dati affidabile, in genere si dovrebbe evitare di eliminare le righe in base alla posizione numerica. Questo perché l'ordine delle righe nei dati potrebbe cambiare in futuro. Un principio generale di un data.frame o delle tabelle del database è che l'ordine delle righe non dovrebbe avere importanza. Se l'ordine è importante, questo dovrebbe essere codificato in una variabile effettiva in data.frame.

Ad esempio, immagina di aver importato un set di dati e di aver eliminato le righe in base alla posizione numerica dopo aver esaminato i dati e identificato i numeri di riga delle righe che desideri eliminare. Tuttavia, in un momento successivo, si entra nei dati non elaborati, si dà un'occhiata e riordina i dati. Il codice di eliminazione delle righe ora eliminerà le righe errate e, peggio ancora, è improbabile che vengano visualizzati errori che avvisano che ciò si è verificato.

Strategia migliore

Una strategia migliore consiste nell'eliminare le righe in base alle proprietà sostanziali e stabili della riga. Ad esempio, se avessi una idvariabile di colonna che identifica in modo univoco ogni caso, puoi usarla.

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

Altre volte, avrai dei criteri di esclusione formali che potrebbero essere specificati e potresti usare uno dei tanti strumenti di sottoimpostazione in R per escludere i casi in base a quella regola.


11

Crea una colonna ID nel tuo frame di dati o usa qualsiasi nome di colonna per identificare la riga. L'uso dell'indice non è corretto da eliminare.

Utilizzare la subsetfunzione per creare una nuova cornice.

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

updated_myData <- subset(myData, id %in% c(1, 3, 5, 7))
print (updated_myData)

9

Per sequenza semplificata:

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

Per sequenza:

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

Per sequenza negativa:

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

O se si desidera effettuare un sottoinsieme selezionando numeri dispari:

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

O se si desidera effettuare il sottoinsieme selezionando numeri dispari, versione 2:

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

O se si desidera sottoinsieme filtrando i numeri pari:

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

Oppure, se si desidera sottoinsieme filtrando i numeri pari, versione 2:

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

5

Elimina Dan da employee.data: non è necessario gestire un nuovo data.frame.

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

0

Ecco una funzione veloce e sporca per rimuovere una riga per indice.

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

Il suo principale difetto è che l'argomento row_index non segue il modello R di essere un vettore di valori. Potrebbero esserci altri problemi poiché ho trascorso solo un paio di minuti a scriverlo e testarlo, e ho iniziato a usare R solo nelle ultime settimane. Eventuali commenti e miglioramenti su questo sarebbero i benvenuti!


0

Per completezza, aggiungerò che questo può essere fatto dplyranche usando slice. Il vantaggio dell'utilizzo di questo è che può far parte di un flusso di lavoro convogliato.

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

Naturalmente, puoi anche usarlo senza tubi.

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

Il formato "non vettoriale" -c(2, 4, 6)significa ottenere tutto ciò che non si trova nelle righe 2, 4 e 6. Ad esempio, usando un intervallo, supponiamo che tu voglia rimuovere le prime 5 righe, potresti farlo slice(df, 6:n()). Per altri esempi, consultare i documenti .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.