¿Cómo elimino filas en un marco de datos?

224

Tengo un marco de datos llamado "mydata" que se ve así:

   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 

Me gustaría eliminar la fila 2,4,6. Por ejemplo, así:

   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 novato
fuente
12
Además, es posible que desee familiarizarse con alguna terminología común para trabajar con datos. Esto se refiere generalmente como de subconjuntos, que, si ha buscado en Google de "trama de datos r subconjunto" que se obtendría con la gran ayuda página UCLA R FAQ . ¡Bienvenido a Stackoverflow, por cierto!
A5C1D2H2I1M1N2O1R2T1
Se agregaron algunas formas adicionales de subconjunto utilizando vectores booleanos, además de la excelente respuesta de @ mrdwab.
Paul Hiemstra
2
@ A5C1D2H2I1M1N2O1R2T1: las preguntas frecuentes de UCLA para subconjuntos R se han movido. Ahora esta aqui .
Mike Sherrill 'Cat Recall'

Respuestas:

340

La idea clave es formar un conjunto de las filas que desea eliminar y mantener el complemento de ese conjunto.

En R, el complemento de un conjunto viene dado por el operador '-'.

Entonces, suponiendo que data.framese llama myData:

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

Por supuesto, no olvide "reasignar" myDatasi desea eliminar esas filas por completo, de lo contrario, R simplemente imprime los resultados.

myData <- myData[-c(2, 4, 6), ]
A5C1D2H2I1M1N2O1R2T1
fuente
59
¡No te olvides de tener en cuenta lo que ,hay allí! ;)
Steven Jeuris
55
¿Qué pasa si su marco de datos es solo una columna? Parece que se cae toda la estructura y genera un vector de los valores
road_to_quantdom
66
@road_to_quantdom, agregue un drop = FALSEallí.
A5C1D2H2I1M1N2O1R2T1
44
"En R, el complemento de un conjunto viene dado por el operador '-'" -> Esta es una redacción muy engañosa. Los índices negativos se eliminan y eso es todo, no hay noción de complemento. Si trabaja con lógica e intenta usarla -, no funcionará, porque el operador complementario para lógica es !. El complemento de c (2,4,6) en las filas preferiría establecerse (c (2,4,6), 1: nrow (myData)), que no es c (-2, -4, -6) , aunque ambos producirían las mismas filas cuando se usan con [.
asac
2
@Speldosa, myData[-c(2, 4, 6),,drop=F]. De hecho, sugeriría que siempre inserte ,drop=Fjusto antes del ]acceso a cualquier matriz.
Aaron McDaid el
82

También puede trabajar con un llamado vector booleano, también conocido como logical:

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

Tenga en cuenta que el !operador actúa como un NOT, es decir !TRUE == FALSE:

myData = myData[!row_to_keep,]

Esto parece un poco engorroso en comparación con la respuesta de @ mrwab (+1 por cierto :)), pero se puede generar un vector lógico sobre la marcha, por ejemplo, cuando el valor de una columna excede un cierto valor:

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

Puede transformar un vector booleano en un vector de índices:

row_to_keep = which(myData$A > 4)

Finalmente, un truco muy bueno es que puedes usar este tipo de subconjuntos no solo para la extracción, sino también para la asignación:

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

donde Ase asigna la columna NA(no un número) donde Aexcede 4.

Paul Hiemstra
fuente
¿Qué pasa si quieres excluirlos? En su ejemplo número 3, si decae
GabrielMontenegro
61

Problemas con la eliminación por número de fila

Para análisis rápidos y sucios, puede eliminar filas de un data.frame por número según la respuesta principal. Es decir,

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

Sin embargo, si está intentando escribir un script de análisis de datos robusto, generalmente debe evitar eliminar filas por posición numérica. Esto se debe a que el orden de las filas en sus datos puede cambiar en el futuro. Un principio general de un data.frame o tablas de base de datos es que el orden de las filas no debería importar. Si el orden es importante, debe codificarse en una variable real en el data.frame.

Por ejemplo, imagine que importó un conjunto de datos y eliminó filas por posición numérica después de inspeccionar los datos e identificar los números de fila de las filas que desea eliminar. Sin embargo, en algún momento posterior, ingresa a los datos sin procesar y echa un vistazo y reordena los datos. Su código de eliminación de filas ahora eliminará las filas incorrectas y, lo que es peor, es poco probable que reciba algún error que le advierta que esto ha ocurrido.

Mejor estrategia

Una mejor estrategia es eliminar filas basadas en propiedades sustantivas y estables de la fila. Por ejemplo, si tuviera una idvariable de columna que identifique de forma única cada caso, podría usarla.

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

Otras veces, tendrá un criterio de exclusión formal que podría especificarse, y podría usar una de las muchas herramientas de subconjunto en R para excluir casos basados ​​en esa regla.

Jeromy Anglim
fuente
11

Cree una columna de identificación en su marco de datos o use cualquier nombre de columna para identificar la fila. Usar el índice no es justo para eliminar.

Use la subsetfunción para crear un nuevo marco.

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

Por secuencia simplificada:

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

Por secuencia:

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

Por secuencia negativa:

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

O si desea subconjunto seleccionando números impares:

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

O si desea subconjunto seleccionando números impares, versión 2:

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

O si desea subconjuntos filtrando números pares:

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

O si desea subconjuntos filtrando números pares, versión 2:

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

Eliminar Dan de employee.data: no es necesario administrar un nuevo data.frame.

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

Aquí hay una función rápida y sucia para eliminar una fila por índice.

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

Su principal defecto es que el argumento row_index no sigue el patrón R de ser un vector de valores. Puede haber otros problemas, ya que solo pasé un par de minutos escribiéndolo y probándolo, y solo comencé a usar R en las últimas semanas. ¡Cualquier comentario y mejora en esto sería muy bienvenido!

Alan Carlyle
fuente
0

Para completar, agregaré que esto se puede hacer también con el dplyruso slice. La ventaja de usar esto es que puede ser parte de un flujo de trabajo canalizado.

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

Por supuesto, también puedes usarlo sin tuberías.

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

El formato "no vector" -c(2, 4, 6)significa obtener todo lo que no está en las filas 2, 4 y 6. Para un ejemplo que usa un rango, digamos que desea eliminar las primeras 5 filas, podría hacerlo slice(df, 6:n()). Para más ejemplos, vea los documentos .

Ryan H.
fuente