Выбор строк из фрейма данных на основе значений в векторе

#r

Вопрос:

У меня есть данные, похожие на эти:

 dt <- structure(list(fct = structure(c(1L, 2L, 3L, 4L, 3L, 4L, 1L, 2L, 3L, 1L, 2L, 3L, 2L, 3L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"), X = c(2L, 4L, 3L, 2L, 5L, 4L, 7L, 2L, 9L, 1L, 4L, 2L, 5L, 4L, 2L)), .Names = c("fct", "X"), class = "data.frame", row.names = c(NA, -15L))
 

Я хочу выбрать строки из этого фрейма данных на основе значений в fct переменной. Например, если я хочу выбрать строки, содержащие «a» или «c», я могу сделать это:

 dt[dt$fct == 'a' | dt$fct == 'c', ]
 

что дает

 1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4
 

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

 vc <- c('a', 'c')
 

Поэтому я попытался

 dt[dt$fct == vc, ]
 

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

Итак, как я могу фильтровать/подмножествовать свои данные на основе содержимого вектора vc ?

Комментарии:

1. попробуйте: dt[dt$fct %in% vc,] В основном == это для одного элемента и %in% для векторного сравнения.

Ответ №1:

Взгляните на ?"%in%" это .

 dt[dt$fct %in% vc,]
   fct X
1    a 2
3    c 3
5    c 5
7    a 7
9    c 9
10   a 1
12   c 2
14   c 4
 

Вы также можете использовать ?is.element :

 dt[is.element(dt$fct, vc),]
 

Ответ №2:

Аналогично приведенному выше, используя filter из dplyr :

 filter(df, fct %in% vc)
 

Ответ №3:

Другим вариантом было бы использование ключа data.table :

 library(data.table)
setDT(dt, key = 'fct')[J(vc)]  # or: setDT(dt, key = 'fct')[.(vc)]
 

что приводит к:

    fct X
1:   a 2
2:   a 7
3:   a 1
4:   c 3
5:   c 5
6:   c 9
7:   c 2
8:   c 4
 

Что это делает:

  • setDT(dt, key = 'fct') преобразует data.frame в a data.table (который является расширенной формой a data.frame ) с fct набором столбцов в качестве ключа.
  • Далее вы можете просто подмножество с vc вектором [J(vc)] с.

ПРИМЕЧАНИЕ: если ключом является переменная фактора/символа, вы также можете использовать setDT(dt, key = 'fct')[vc] , но это не сработает, если vc это числовой вектор. Когда vc является числовым вектором и не завернут в J() или .() , vc будет работать как rowindex.

Более подробное объяснение концепции ключей и подмножеств можно найти в разделе Ключи виньетки и подмножество на основе быстрого двоичного поиска.

Альтернатива, предложенная @Frank в комментариях:

 setDT(dt)[J(vc), on=.(fct)]
 

Если vc содержит значения , которых нет в dt , вам нужно будет добавить nomatch = 0 :

 setDT(dt, key = 'fct')[J(vc), nomatch = 0]
 

или:

 setDT(dt)[J(vc), on=.(fct), nomatch = 0]
 

Комментарии:

1. Я не мог заставить это работать, когда вектор и переменная в data.table являются числовыми. Есть какие-нибудь идеи?

2. @GauravSinghal обновил ответ, метод в предыдущей версии работал для столбцов символов/факторов; обновленный метод также работает для целых/числовых столбцов