Filtrar filas de data.frame por una condición lógica

155

Quiero filtrar filas a data.framepartir de una condición lógica. Supongamos que tengo un marco de datos como

   expr_value     cell_type
1    5.345618 bj fibroblast
2    5.195871 bj fibroblast
3    5.247274 bj fibroblast
4    5.929771          hesc
5    5.873096          hesc
6    5.665857          hesc
7    6.791656          hips
8    7.133673          hips
9    7.574058          hips
10   7.208041          hips
11   7.402100          hips
12   7.167792          hips
13   7.156971          hips
14   7.197543          hips
15   7.035404          hips
16   7.269474          hips
17   6.715059          hips
18   7.434339          hips
19   6.997586          hips
20   7.619770          hips
21   7.490749          hips

Lo que quiero es obtener un nuevo marco de datos que se vea igual pero solo tenga los datos para un tipo_célula. Por ejemplo, subconjunto / seleccionar filas que contiene el tipo de celda "hesc":

   expr_value     cell_type
1    5.929771          hesc
2    5.873096          hesc
3    5.665857          hesc

O bien tipo de célula "fibroblastos bj" o "hesc":

   expr_value     cell_type
1    5.345618 bj fibroblast
2    5.195871 bj fibroblast
3    5.247274 bj fibroblast
4    5.929771          hesc
5    5.873096          hesc
6    5.665857          hesc

¿Hay alguna manera fácil de hacer esto?

He intentado:

expr[expr[2] == 'hesc']
# [1] "5.929771" "5.873096" "5.665857" "hesc"     "hesc"     "hesc"    

si el marco de datos original se llama "expr", pero da los resultados en un formato incorrecto como puede ver.

lhahne
fuente

Respuestas:

210

Para seleccionar filas de acuerdo con un 'cell_type' (por ejemplo, 'hesc'), use ==:

expr[expr$cell_type == "hesc", ]

Para seleccionar filas según dos o más 'cell_type' diferentes (por ejemplo, 'hesc' o 'bj fibroblast'), use %in%:

expr[expr$cell_type %in% c("hesc", "bj fibroblast"), ]
aprendiz
fuente
28
Tenga en cuenta que la ==función recogerá todos los registros de NA y "hesc", mientras %in%que no lo hará.
Matt Parker el
Me pregunto si esto funciona ahora. No pude subconjurar el marco de datos basado en la condición de esta manera.
Sumanth Lazarus el
85

Uso subset(para uso interactivo)

subset(expr, cell_type == "hesc")
subset(expr, cell_type %in% c("bj fibroblast", "hesc"))

o mejor dplyr::filter()

filter(expr, cell_type %in% c("bj fibroblast", "hesc"))
rcs
fuente
37
¡Cuidado! La documentación de subsettiene una gran ADVERTENCIA: "Esta es una función de conveniencia para uso interactivo. Para la programación es mejor usar las funciones de subconjunto estándar como [, y en particular la evaluación no estándar d del subconjunto de argumentos puede tener consecuencias inesperadas ".
Aleksandar Dimitrov
33

La razón expr[expr[2] == 'hesc']no funciona es que para un marco de datos, x[y]selecciona columnas, no filas. Si desea seleccionar filas, cambie a la sintaxis en su x[y,]lugar:

> expr[expr[2] == 'hesc',]
  expr_value cell_type
4   5.929771      hesc
5   5.873096      hesc
6   5.665857      hesc
Ken Williams
fuente
¡Esto también recogerá cualquier NAregistro! Por lo tanto, no aplicable. La razón por la que parecía ser cierto resultó del hecho de que el marco de datos expr no tiene NAen la columna filtrada. Si existe NA, su camino no es aplicable como dije antes.
Erdogan CEVHER
26

Podrías usar el dplyrpaquete:

library(dplyr)
filter(expr, cell_type == "hesc")
filter(expr, cell_type == "hesc" | cell_type == "bj fibroblast")
Nathaneastwood
fuente
5

Nadie parece haber incluido qué función. También puede resultar útil para filtrar.

expr[which(expr$cell == 'hesc'),]

Esto también manejará los NA y los eliminará del marco de datos resultante.

Al ejecutar esto en un marco de datos 9840 por 24 50000 veces, parece que el método tiene un tiempo de ejecución un 60% más rápido que el método% en%.

eigenfoo
fuente
4

Estaba trabajando en un marco de datos y no tuve suerte con las respuestas proporcionadas, siempre devolvió 0 filas, así que encontré y usé grepl:

df = df[grepl("downlink",df$Transmit.direction),]

Que básicamente recortó mi marco de datos solo a las filas que contenían "enlace descendente" en la columna Dirección de transmisión. PD: si alguien puede adivinar por qué no veo el comportamiento esperado, deje un comentario.

Específicamente a la pregunta original:

expr[grepl("hesc",expr$cell_type),]

expr[grepl("bj fibroblast|hesc",expr$cell_type),]
Justin Harbor
fuente
3

A veces, la columna que desea filtrar puede aparecer en una posición diferente que el índice de columna 2 o tener un nombre de variable.

En este caso, simplemente puede hacer referencia al nombre de la columna que desea filtrar como:

columnNameToFilter = "cell_type"
expr[expr[[columnNameToFilter]] == "hesc", ]
Daniel Bonetti
fuente
¡Esto también recogerá cualquier NAregistro! Por lo tanto, no aplicable.
Erdogan CEVHER
0

podemos usar la biblioteca data.table

  library(data.table)
  expr <- data.table(expr)
  expr[cell_type == "hesc"]
  expr[cell_type %in% c("hesc","fibroblast")]

o filtrar usando el %like%operador para la coincidencia de patrones

 expr[cell_type %like% "hesc"|cell_type %like% "fibroblast"]
Varn K
fuente