Быстрый способ выбора строк в таблице в R?

Я ищу быстрый способ извлечь большое количество строк из еще большей таблицы. Верхняя часть моей таблицы выглядит следующим образом:

> head(dbsnp)

      snp      gene distance
rs5   rs5     KRIT1        1
rs6   rs6   CYP51A1        1
rs7   rs7 LOC401387        1
rs8   rs8      CDK6        1
rs9   rs9      CDK6        1
rs10 rs10      CDK6        1

И размеры:

> dim(dbsnp)
[1] 11934948        3

Я хочу выбрать строки с именами, содержащимися в списке:

> head(features)
[1] "rs1367830" "rs5915027" "rs2060113" "rs1594503" "rs1116848" "rs1835693"

> length(features)
[1] 915635

Неудивительно, что простой способ сделать это temptable = dbsnp[features,] занимает довольно много времени.

Я искал способы сделать это с помощью пакета sqldf в R. Я подумал, что это может быть быстрее. К сожалению, я не могу понять, как выбирать строки с определенными именами в SQL.

Спасибо.


person Gordon Freeman    schedule 30.08.2012    source источник
comment
ознакомьтесь с пакетом data.table. вы можете сделать это с помощью ключей. Идентичны ли имена ваших строк столбцу snp?   -  person Justin    schedule 30.08.2012
comment
Да, это одно и то же. Я посмотрю в data.table.   -  person Gordon Freeman    schedule 30.08.2012
comment
Просто ради интереса, знает ли кто-нибудь, есть ли разница во времени, если вы сначала получите номера строк с помощью некоторого механизма, такого как foo<-rownames(dbsnp); bar<-which(foo%in%features,arr.ind=TRUE); temptable<-dbsnp[c(bar),] (я знаю, что это неправильный синтаксис R для этого, но вы поняли идею).   -  person Carl Witthoft    schedule 30.08.2012


Ответы (3)


Поначалу большинство людей попробовали бы это следующим образом:

dbsnp[ rownames(dbsnp) %in% features, ]  # which is probably slower than your code

Поскольку вы говорите, что это занимает много времени, я подозреваю, что вы превысили объем оперативной памяти и начали использовать виртуальную память. Вам следует выключить систему, а затем перезапустить ее, используя только R в качестве работающего приложения, и посмотреть, сможете ли вы избежать «виртуального» перехода.

person IRTFM    schedule 30.08.2012
comment
Я попытался выбрать строки, как вы и предполагали, «обычно». Это намного быстрее (я не знал, что вы можете делать% в% из списков в списки). - person Gordon Freeman; 30.08.2012
comment
Судя по тому, что вы показали, я думаю, что оба этих объекта были атомарными векторами, а не списками R. Признаюсь, я был немного удивлен, что это было быстрее. - person IRTFM; 31.08.2012
comment
Круто - я учту это различие в следующий раз. На самом деле я только что узнал разницу между ними из вашего сообщения здесь: stackoverflow.com/questions/8594814/ - person Gordon Freeman; 31.08.2012

data.table решение:

library(data.table)
dbsnp <- structure(list(snp = c("rs5", "rs6", "rs7", "rs8", "rs9", "rs10"
), gene = c("KRIT1", "CYP51A1", "LOC401387", "CDK6", "CDK6", 
"CDK6"), distance = c(1L, 1L, 1L, 1L, 1L, 1L)), .Names = c("snp", 
"gene", "distance"), class = "data.frame", row.names = c("rs5", 
"rs6", "rs7", "rs8", "rs9", "rs10"))

DT <- data.table(dbsnp, key='snp')
features <- c('rs5', 'rs7', 'rs9')
DT[features]

   snp      gene distance
1: rs5     KRIT1        1
2: rs7 LOC401387        1
3: rs9      CDK6        1
person Justin    schedule 30.08.2012

Используя sqldf, вам понадобится rownames = TRUE, после чего вы можете запросить rownames, используя row_names:

library(sqldf)

## input

test<-read.table(header=T,text="      snp      gene distance
rs5   rs5     KRIT1        1
rs6   rs6   CYP51A1        1
rs7   rs7 LOC401387        1
rs8   rs8      CDK6        1
rs9   rs9      CDK6        1
rs10 rs10      CDK6        1
")
features<-c("rs5","rs7","rs10")

## calculate

inVar <- toString(shQuote(features, type = "csh")) # 'rs5','rs7','rs10'

fn$sqldf("SELECT * FROM test t
          WHERE t.row_names IN ($inVar)"
           , row.names = TRUE)

## result
#      snp      gene distance
#rs5   rs5     KRIT1        1
#rs7   rs7 LOC401387        1
#rs10 rs10      CDK6        1

ОБНОВЛЕНИЕ: Альтернативно, если fet - это фрейм данных, столбец features которого содержит необходимые элементы для поиска:

fet <- data.frame(features)
sqldf("SELECT t.* FROM test t
          WHERE t.row_names IN (SELECT features FROM fet)"
           , row.names = TRUE)

Также, если бы данные были достаточно большими, мы могли бы ускорить их использование индексов. См. главную страницу sqldf для получения этой и других сведений.

person shhhhimhuntingrabbits    schedule 30.08.2012