Ускорить анализ

#performance #r #dataframe

#Производительность #r #фрейм данных

Вопрос:

У меня есть 2 фрейма данных в R, например df и dfrefseq.

 df<-data.frame( chr =  c("chr1","chr1","chr1","chr4")
    , start = c(843294,4329248,4329423,4932234)
    , stop = c(845294,4329248,4529423,4935234)
    , genenames= c("HTA","OdX","FEA","MGA")
)
dfrefseq<-data.frame( chr =  c("chr1","chr1","chr1","chr2")
    , start = c(843294,4329248,4329423,4932234)
    , stop = c(845294,4329248,4529423,4935234)
    , genenames= c("tra","FGE","FFs","FAA")
)
  

Я хочу проверить, что каждый ген в df witch gene в dfrefseq находится ближе всего к выбранному гену df.
Сначала я выбрал «chr1» в обоих фреймах данных.
Затем я вычислил для первого гена в readschr1 расстояние между участками start-start start-stop stop-start и stop-stop-stop.
Сумма этих вычислений говорит все о расстоянии. Мой вопрос здесь в том, как я могу ускорить этот анализ? Потому что сейчас я протестировал только 1 ген на основе фрейма данных, но мне нужно протестировать 2000 генов.

 readschr1 <- subset(df,df[,1]=="chr1") 
refseqchr1 <- subset(dfrefseq,dfrefseq[,1]=="chr1") 

names<-list()
read_start_start<-list()
read_start_stop<-list() 
read_stop_start<-list()
read_stop_stop<-list()

for (i in 1:nrow(refseqchr1)) {
startstart<-abs(readschr1[1,2] - refseqchr1[i,2])
startstop<-abs(readschr1[1,2] - refseqchr1[i,3])
stopstart<-abs(readschr1[1,3] - refseqchr1[i,2])
stopstop<-abs(readschr1[1,3] - refseqchr1[i,3])
read_start_start[[i]]<- matrix(startstart)
read_start_stop[[i]]<- matrix(startstop)
read_stop_start[[i]]<- matrix(stopstart)
read_stop_stop[[i]]<- matrix(stopstop)
names[[i]]<-matrix(refseqchr1[i,4])
}
table<-cbind(names, read_start_start, read_start_stop, read_stop_start, read_stop_stop)


sumtotalcolumns<-as.numeric(table[,2])   as.numeric(table[,3])  as.numeric(table[,4])   as.numeric(table[,5])
test<-cbind(table, sumtotalcolumns)
test1<-test[order(as.vector(test$sumtotalcolumns)), ]
  

Спасибо!

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

1. обратите внимание, что df является функцией в R. Я бы постарался по возможности избегать его использования в будущем. dat хорошее название для использования, ИМХО. То же самое с table и names .

Ответ №1:

Пакет Bioconductor GenomicRanges предназначен для работы с данными такого типа

 source('http://bioconductor.org/biocLite.R')
biocLite('GenomicRanges')                      # one-time installation
  

затем

 library(GenomicRanges)
gr <- with(df,
           GRanges(factor(chr, levels=paste("chr", 1:4, sep="")),
                   IRanges(start, stop), genenames=genenames))
grrefseq <- with(dfrefseq,
                 GRanges(factor(chr, levels=paste("chr", 1:4, sep="")),
                         IRanges(start, stop), genenames=genenames))
  

и

 > nearest(gr, grrefseq)
[1]  1  2  3 NA
  

Ответ №2:

Вы можете merge объединить два отдельных фрейма данных вместе, чтобы сформировать одну таблицу, а затем использовать векторизованные операции. Ключ к merge заключается в том, чтобы указать общий столбец (столбцы) между data.frames и указать ему, что делать, когда есть случаи, которые не совпадают. Указание all = TRUE вернет все строки и заполнит NAs, если в другом data.frame нет совпадений, т.е. в данном случае ch2 и ch4. После объединения данных.фреймов выполняется простое упражнение по вычитанию разных столбцов друг из друга, а затем суммированию четырех интересующих столбцов. Я использую transform , чтобы сократить ввод текста, необходимый для выполнения вычитания.

 zz <- merge(df, dfrefseq, by = "chr", all = TRUE)

zz <- transform(zz, 
    read_start_start = abs(start.x - start.y)
  , read_start_stop = abs(start.x - stop.y)
  , read_stop_start = abs(stop.x - start.y)
  , read_stop_stop = abs(stop.x - stop.y)
)

zz <- transform(zz,
  sum_total_columns = read_start_start   read_start_stop   read_stop_start   read_stop_stop
  )
  

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

 require(plyr)
ddply(zz, c("chr", "genenames.x"), function(x) x[which.min(x$sum_total_columns) ,])
  

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

1. Дорогой Чейз, большое спасибо за ваше решение. Он работает с моим набором данных. Единственное, что мои данные zz очень большие. Вы знаете, возможно ли сохранить только результат с наименьшей суммой суммарных значений. Я думал, что-то с уникальной функцией.

2. @Lisann — Добавлено к моему ответу, чтобы ответить на ваш дополнительный вопрос.

3. Вы можете изменить all = TRUE в merge на all.x = TRUE и получить некоторое ускорение.