Я использую data.table::foverlaps
в контексте проблем перекрывающихся интервалов геномики .
Недавно я попытался найти эквивалент foverlaps в Python, потому что было бы гораздо приятнее использовать только один язык вместо комбинирования Python & R каждый раз, когда мне приходилось копаться в результатах анализа.
Конечно, я не первый, кто задает вопрос о нахождении эквивалента R foverlaps в python, применимых в Python pandas. Это самый актуальный пост, который я нашел на SO:
2015 Объединить кадры данных панд, где одно значение находится между двумя другими
2016 R эквивалент эквивалента в Python
2017 Как объединить два кадра данных, для которых значения столбцов находятся в определенном диапазоне?
2018 Как воспроизвести такой же вывод foverlaps в R со слиянием панд в python?
Дело в том, что я вообще не специалист по Python. Поэтому я выбрал ответ, наиболее актуальный / понятный для меня, sqlite3
.
Вот как я делаю это в R:
library(data.table)
interv1 <- cbind(seq(from = 3, to = 40, by = 4),seq(from = 5, to = 50, by = 5), c(rep("blue",5), rep("red", 5)), rep("+",10))
interv2 <- cbind(seq(from = 3, to = 40, by = 4),seq(from = 5, to = 50, by = 5), c(rep("blue",5), rep("red", 5)), rep("-",10))
interv <- rbind(interv1, interv2)
interv <- data.table(interv)
colnames(interv) <- c('start', 'stop', 'color', 'strand')
interv$start <- as.integer(interv$start)
interv$stop <- as.integer(interv$stop)
interv$stop <- interv$stop -1
interv$cov <- runif(n=nrow(interv), min = 10, max = 200)
to_match <- data.table(cbind(rep(seq(from = 4, to = 43, by = 4),2), rep(c(rep("blue", 5), rep("red", 5)), 2), c(rep("-", 10), rep("+", 10))))
colnames(to_match) <- c('start', 'color', 'strand')
to_match$stop <- to_match$start
to_match$start <- as.integer(to_match$start)
to_match$stop <- as.integer(to_match$stop)
setkey(interv, color, strand, start, stop)
setkey(to_match, color, strand, start, stop)
overlapping_df <- foverlaps(to_match,interv)
#write.csv(x = interv, file = "Documents/script/SO/wig_foverlaps_test.txt", row.names = F)
#write.csv(x = to_match, file = "Documents/script/SO/cov_foverlaps_test.txt", row.names = F)
И вот как я пытался воспроизвести его на python:
import pandas as pd
import sqlite3
cov_table = pd.DataFrame(pd.read_csv('SO/cov_foverlaps_test.txt', skiprows = [0], header=None))
cov_table.columns = ['start', 'stop', 'chrm', 'strand', 'cov']
cov_table.stop = cov_table.stop - 1
wig_file = pd.DataFrame(pd.read_csv('SO/wig_foverlaps_test.txt', header=None, skiprows = [0]))
wig_file.columns = ['i_start', 'chrm', 'i_strand', 'i_stop']
cov_cols = ['start','stop','chrm','strand','cov']
fract_cols = ['i_start','i_stop','chrm','i_strand']
cov_table = cov_table.reindex(columns = cov_cols)
wig_file = wig_file.reindex(columns = fract_cols)
cov_table.start = pd.to_numeric(cov_table['start'])
cov_table.stop = pd.to_numeric(cov_table['stop'])
wig_file.i_start = pd.to_numeric(wig_file['i_start'])
wig_file.i_stop = pd.to_numeric(wig_file['i_stop'])
conn = sqlite3.connect(':memory:')
cov_table.to_sql('cov_table', conn, index=False)
wig_file.to_sql('wig', conn, index=False)
qry = '''
select
start PresTermStart,
stop PresTermEnd,
cov RightCov,
i_start pos,
strand Strand
from
cov_table join wig on
i_start between start and stop and
cov_table.strand = wig.i_strand
'''
test = pd.read_sql_query(qry, conn)
Независимо от того, что я изменяю код, я всегда нахожу некоторые небольшие различия в выводе (тест), в этом примере я пропускаю две строки в итоговой таблице Python, где значение, которое должно находиться в диапазоне и равен концу диапазона:
пропущенная строка:
> 19 24 141.306318 24 +
>
> 19 24 122.923700 24 -
Наконец, я боюсь, что если я найду правильный способ сделать это с sqlite3
, разница во времени вычислений с data.table::foverlaps
будет слишком большой.
Подытожить:
- Мой первый вопрос - это где я ошибся в своем коде?
- Есть ли подход, который был бы более подходящим и близким к фоверлапсу?
с точки зрения скорости вычислений?
Спасибо, что прочитали, я надеюсь, что этот пост подходит для SO.