#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 и получить некоторое ускорение.