Фильтровать строки data.frame по логическому условию

155

Я хочу отфильтровать строки на data.frameоснове логического условия. Давайте предположим, что у меня есть данные как

   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

Я хочу получить новый фрейм данных, который выглядит одинаково, но содержит данные только для одного типа cell_type. Например, подмножество / выбрать строки, которые содержат тип ячейки "hesc":

   expr_value     cell_type
1    5.929771          hesc
2    5.873096          hesc
3    5.665857          hesc

Или тип клетки "фибробласт bj" или "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

Есть ли простой способ сделать это?

Я пробовал:

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

если исходный фрейм данных называется «expr», но он дает результаты в неправильном формате, как вы можете видеть.

lhahne
источник

Ответы:

210

Чтобы выбрать строки в соответствии с одним типом ячейки (например, hesc), используйте ==:

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

Чтобы выбрать строки в соответствии с двумя или более различными типами 'cell_type' (например, 'hesc' или 'bj fibroblast'), используйте %in%:

expr[expr$cell_type %in% c("hesc", "bj fibroblast"), ]
learnr
источник
28
Имейте в виду, что ==функция будет собирать любые записи NA, а также "hesc", тогда как %in%не будет.
Мэтт Паркер
Интересно, работает ли это сейчас? Таким образом, я не смог установить подкадр данных в зависимости от условий.
Сумант Лазарь
85

Использовать subset(для интерактивного использования)

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

или лучше dplyr::filter()

filter(expr, cell_type %in% c("bj fibroblast", "hesc"))
система охлаждения реактора
источник
37
Осторожный! В документации subsetесть большое ПРЕДУПРЕЖДЕНИЕ: «Это удобная функция, предназначенная для интерактивного использования. Для программирования лучше использовать стандартные функции поднабора, такие как [, и, в частности, нестандартная оценка подмножества аргументов может иметь непредвиденные последствия». «.
Александар Димитров
33

Причина expr[expr[2] == 'hesc']не работает в том, что для фрейма данных x[y]выбираются столбцы, а не строки. Если вы хотите выбрать строки, измените их на синтаксис x[y,]:

> expr[expr[2] == 'hesc',]
  expr_value cell_type
4   5.929771      hesc
5   5.873096      hesc
6   5.665857      hesc
Кен Уильямс
источник
Это подберет и любые NAзаписи! Следовательно, не применимо. Причина, по которой это казалось правдой, объясняется тем, что NAв фильтрованном столбце нет данных exprrame. Если есть NA, ваш путь не применим, как я уже говорил.
Эрдоган СЕВЕР
26

Вы можете использовать dplyrпакет:

library(dplyr)
filter(expr, cell_type == "hesc")
filter(expr, cell_type == "hesc" | cell_type == "bj fibroblast")
nathaneastwood
источник
5

Кажется, никто не включил функцию which. Это также может оказаться полезным для фильтрации.

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

Это также обработает NA и удалит их из результирующего кадра данных.

При выполнении этого на 9840 на 24 фрейме данных 50000 раз кажется, что метод с тем же временем выполнения работает на 60% быстрее, чем метод% in%.

eigenfoo
источник
4

Я работал над фреймом данных и без удачи с предоставленными ответами, он всегда возвращал 0 строк, поэтому я нашел и использовал grepl:

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

Который в основном урезал мой фрейм данных только до тех строк, которые содержали нисходящую линию в столбце направления передачи. PS Если кто-то может догадаться, почему я не вижу ожидаемого поведения, пожалуйста, оставьте комментарий.

Конкретно на оригинальный вопрос:

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

expr[grepl("bj fibroblast|hesc",expr$cell_type),]
Джастин Харбор
источник
3

Иногда столбец, который вы хотите отфильтровать, может оказаться в другом положении, чем столбец с индексом 2, или иметь имя переменной.

В этом случае вы можете просто ссылаться на имя столбца, который вы хотите отфильтровать:

columnNameToFilter = "cell_type"
expr[expr[[columnNameToFilter]] == "hesc", ]
Даниэль Бонетти
источник
Это подберет и любые NAзаписи! Следовательно, не применимо.
Эрдоган СЕВЕР
0

мы можем использовать библиотеку data.table

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

или фильтр с использованием %like%оператора для сопоставления с образцом

 expr[cell_type %like% "hesc"|cell_type %like% "fibroblast"]
Варн К
источник