R или панды.Если значение столбца в df A в диапазоне, заданном 2 столбцами в df B, вывести строку в A - PullRequest
0 голосов
/ 28 сентября 2019

Используя python pandas или R:

У меня есть фрейм данных A с миллионами строк:

CHR SNP POS
1 rs2073813 753541
1 rs3131969 754182
2 rs3131968 754192
2 rs3131967 754334
3 rs3115859 754503
3 rs3131966 900000

и еще один фрейм данных B (также миллионы строк):

CHR start end 
1 700500 833300
2 1000 20000
2 59998 60000 
3 700000 800000

Для каждого «POS» в A я хочу проверить, присутствует ли он в пределах диапазона, заданного «start» и «end» B (проверьте каждую строку в B).Кроме того, CHR в A также должен соответствовать CHR в B. Если эти условия выполняются, выведите строку в A. Строки в A уникальны и отсортированы в соответствии с POS в A. Каждая строка в B также уникальна.

Например, POS 753541 от A находится в диапазоне от 700500 до 833300, и CHR = 1 от A и CHR = 1 B также совпадают, поэтому выведите:

1 rs2073813 753541

В конце я хочу получитьфрейм данных C, как это:

CHR SNP POS
1 rs2073813 753541
1 rs3131969 754182
3 rs3115859 754503

Ответы [ 2 ]

0 голосов
/ 28 сентября 2019

В своем редакторе cddt предложил использовать неэквивалентное объединение .

К сожалению, неэквивалентные соединения несколькосложно.Чтобы получить ожидаемый результат, нам нужно указать POS из первого data.table A:

library(data.table)
setDT(A) # coerce to data.table
setDT(B) 
A[B, on = .(CHR, POS >= start, POS <= end), .(CHR, SNP, x.POS), nomatch = 0]
   CHR       SNP    POS
1:   1 rs2073813 753541
2:   1 rs3131969 754182
3:   3 rs3115859 754503

Это достигается с помощью префиксаx.

В качестве альтернативы (и, возможно, несколько более интуитивно) мы можем вернуть индексы строк соответствующих строк на

A[B, on = .(CHR, POS >= start, POS <= end), nomatch = 0, which = TRUE]
[1] 1 2 5

и подмножество A соответственно:

A[A[B, on = .(CHR, POS >= start, POS <= end), nomatch = 0, which = TRUE]]
   CHR       SNP    POS
1:   1 rs2073813 753541
2:   1 rs3131969 754182
3:   3 rs3115859 754503

foverlaps()

Это менее элегантная альтернатива:

foverlaps(A[, POS2 := POS], setkey(B), by.x = c("CHR", "POS", "POS2"), nomatch = 0)
   CHR  start    end       SNP    POS   POS2
1:   1 700500 833300 rs2073813 753541 753541
2:   1 700500 833300 rs3131969 754182 754182
3:   3 700000 800000 rs3115859 754503 754503

Данные

library(data.table)

A <- fread("CHR SNP POS
1 rs2073813 753541
1 rs3131969 754182
2 rs3131968 754192
2 rs3131967 754334
3 rs3115859 754503
3 rs3131966 900000")

B <- fread("CHR start end 
1 700500 833300
2 1000 20000
2 59998 60000 
3 700000 800000")
0 голосов
/ 28 сентября 2019

Используя data.table, настройте образцы данных:

library(data.table)
A <- data.table(CHR = c(1,1,2,2,3,3), SNP = c('rs2073813', 'rs3131969', 'rs3131968', 'rs3131967', 'rs3115859', 'rs3131966'), POS = c(753541,754182,754192,754334,754503,900000))
B <- data.table(CHR = c(1,2,2,3), start = c(700500, 1000, 59998, 700000), end = c(833300, 20000, 60000, 800000))

Затем объедините A и B на CHR:

merged_all <- merge(x = A, y = B, on = 'CHR')

Затем отфильтруйте объединенныеданные включают только строки и столбцы, которые соответствуют вашим критериям:

out <- merged_all[(POS > start & end > POS), .(CHR, SNP, POS)]
> out
   CHR       SNP    POS
1:   1 rs2073813 753541
2:   1 rs3131969 754182
3:   3 rs3115859 754503

Редактировать:

Обновление с гораздо более эффективным вариантом:

out <- A[B, on = .(CHR, POS >= start, POS <= end), .(CHR, SNP, POS), nomatch = 0]
> out
   CHR       SNP    POS
1:   1 rs2073813 700500
2:   1 rs3131969 700500
3:   3 rs3115859 700000

Это соединяет таблицы напрямую.

Примечание: неясно, требуются ли вам инклюзивные или эксклюзивные диапазоны (> или >=).Вы можете настроить соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...