Filtrer les lignes data.frame par une condition logique


155

Je souhaite filtrer les lignes à partir d'une data.framecondition logique. Supposons que j'ai une trame de données comme

   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

Ce que je veux, c'est obtenir une nouvelle trame de données qui a la même apparence mais qui ne contient que les données d'un type de cellule. Par exemple, sous-ensemble / sélectionnez des lignes contenant le type de cellule "hesc":

   expr_value     cell_type
1    5.929771          hesc
2    5.873096          hesc
3    5.665857          hesc

Ou soit le type de cellule «fibroblaste bj» ou «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

Y a-t-il un moyen simple de le faire?

J'ai essayé:

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

si le bloc de données d'origine est appelé "expr", mais il donne les résultats dans un format incorrect comme vous pouvez le voir.

Réponses:


210

Pour sélectionner des lignes en fonction d' un 'cell_type' (par exemple 'hesc'), utilisez ==:

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

Pour sélectionner des lignes en fonction de deux ou plusieurs 'cell_type' différents (par exemple, soit 'hesc' ou 'bj fibroblast'), utilisez %in%:

expr[expr$cell_type %in% c("hesc", "bj fibroblast"), ]

28
Sachez que la ==fonction récupérera tous les enregistrements NA ainsi que "hesc", alors que %in%ce ne sera pas le cas.
Matt Parker

Je me demande si cela fonctionne maintenant? Je n'ai pas pu sous-définir le dataframe en fonction de l'état de cette manière.
Sumanth Lazarus

85

Utilisation subset(pour une utilisation interactive)

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

ou mieux dplyr::filter()

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

37
Prudent! La documentation de subseta un gros AVERTISSEMENT: "Il s'agit d'une fonction pratique destinée à être utilisée de manière interactive. Pour la programmation, il est préférable d'utiliser les fonctions de sous-ensembles standard comme [, et en particulier l'évaluation non standard du sous - ensemble d' arguments peut avoir des conséquences imprévues . "
Aleksandar Dimitrov

33

La raison expr[expr[2] == 'hesc']ne fonctionne pas est que pour un bloc de données, x[y]sélectionne des colonnes, pas des lignes. Si vous souhaitez sélectionner des lignes, passez x[y,]plutôt à la syntaxe :

> expr[expr[2] == 'hesc',]
  expr_value cell_type
4   5.929771      hesc
5   5.873096      hesc
6   5.665857      hesc

Cela ramassera également tous les NAenregistrements! Par conséquent, sans objet. La raison pour laquelle cela semblait vrai résultait du fait que expr dataframe n'a pas NAdans la colonne filtrée. S'il y en a NA, votre chemin n'est pas applicable comme je l'ai déjà dit.
Erdogan CEVHER

26

Vous pouvez utiliser le dplyrpackage:

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

5

Personne ne semble avoir inclus la fonction which. Cela peut également s'avérer utile pour le filtrage.

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

Cela gérera également les NA et les supprimera de la trame de données résultante.

En exécutant ceci sur une trame de données 9840 x 24 50000 fois, il semble que la méthode which a un temps d'exécution 60% plus rapide que la méthode% in%.


4

Je travaillais sur un dataframe et n'ayant pas de chance avec les réponses fournies, il retournait toujours 0 lignes, donc j'ai trouvé et utilisé grepl:

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

Ce qui a essentiellement réduit mon dataframe aux seules lignes qui contenaient "downlink" dans la colonne de direction de transmission. PS Si quelqu'un peut deviner pourquoi je ne vois pas le comportement attendu, veuillez laisser un commentaire.

Plus précisément à la question initiale:

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

expr[grepl("bj fibroblast|hesc",expr$cell_type),]

3

Parfois, la colonne que vous souhaitez filtrer peut apparaître dans une position différente de l'index de colonne 2 ou avoir un nom de variable.

Dans ce cas, vous pouvez simplement faire référence au nom de la colonne que vous souhaitez filtrer comme:

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

Cela ramassera également tous les NAenregistrements! Par conséquent, sans objet.
Erdogan CEVHER

0

nous pouvons utiliser la bibliothèque data.table

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

ou filtre à l'aide de l' %like%opérateur pour la correspondance de modèle

 expr[cell_type %like% "hesc"|cell_type %like% "fibroblast"]

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.