Объединение оператора ifelse с функцией shift data.table в R - PullRequest
0 голосов
/ 01 февраля 2019

Я пытаюсь понять, как бы я объединил оператор ifelse с функцией shift в data.table.Мои данные выглядят так:

DF <- structure(list(CHR = c(1, 1, 1, 1, 1,1), 
SNP = c("rs2494631", "rs4648637", "rs2494627", "rs11122119", "rs1844583","rs2292242"), 
BP = c(2399149, 2401364, 2402499, 6768856, 8383469, 8385059), 
KBdist= c(NA, 2215, 1135, 4366357, 1614613, 1590), 
locus = c(1, NA, NA, NA, NA, NA)), 
.Names = c("CHR","SNP","BP","KBdist","locus"), 
row.names = c(NA, 6L), 
class = "data.frame")

> df

CHR SNP        BP       KBdist   locus
1   rs2494631  2399149  NA       1
1   rs4648637  2401364  2215     NA
1   rs2494627  2402499  1135     NA
1   rs11122119 6768856  4366357  NA
1   rs1844583  8383469  1614613  NA
1   rs2292242  8385059  1590     NA

, и я пытаюсь добиться следующего: «Если CHR равен строке выше, а KBdist меньше 500 000, сделайте локус равным строке выше, иначедобавить один к значению строки выше ".Что приведет к выводу, который выглядит следующим образом:

CHR SNP        BP       KBdist   locus
1   rs2494631  2399149  NA       1
1   rs4648637  2401364  2215     1
1   rs2494627  2402499  1135     1
1   rs11122119 6768856  4366357  2
1   rs1844583  8383469  1614613  3
1   rs2292242  8385059  1590     3

Я знаю, что я могу использовать shift для доступа к значениям в строке выше, например:

DF<-DF[ , KBdist := BP - shift(BP, 1L, type="lag")]

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

Любая помощь будет принята с благодарностью.

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 02 февраля 2019

Другая возможность использует cumsum:

setDT(DF)[, locus := cumsum(c(1L, (CHR!=shift(CHR,1L) | KBdist>=500e3)[-1L]))]

выход:

   CHR        SNP      BP  KBdist locus
1:   1  rs2494631 2399149      NA     1
2:   1  rs4648637 2401364    2215     1
3:   1  rs2494627 2402499    1135     1
4:   1 rs11122119 6768856 4366357     2
5:   1  rs1844583 8383469 1614613     3
6:   1  rs2292242 8385059    1590     3
0 голосов
/ 01 февраля 2019

Вот решение, которое решает задачу в base R, хотя - data.table здесь не используется.

# logical vector with our condition tested
ind <- (diff(DF$CHR) == 0 & DF$KBdist[-1] < 5e+5)
# populating the 'locus' column   ---   notice the '<<-'
vapply(2:nrow(DF), function (k) DF$locus[k] <<- DF$locus[k-1] + 1 - ind[k-1], numeric(1)) 
# [1] 1 1 2 3 3
DF
#   CHR        SNP      BP  KBdist locus
# 1   1  rs2494631 2399149      NA     1
# 2   1  rs4648637 2401364    2215     1
# 3   1  rs2494627 2402499    1135     1
# 4   1 rs11122119 6768856 4366357     2
# 5   1  rs1844583 8383469 1614613     3
# 6   1  rs2292242 8385059    1590     3

vapply(...) возвращает столбец locus и перезаписывает его.

Примечание

Обратите внимание, что я использовал <<- внутри функции, чтобы перезаписать значение DF$locus[k].Если вам не нравится этот аспект, просто поменяйте <<- на <- и замените vapply(...) на DF$locus[-1] <- vapply(...).

...