我在R.工作.我有一个数据框,其中包含染色体上的起始位置和结束位置(其中整数表示染色体上的坐标)例如:
start end
1 5
3 7
4 10
12 7 (inverted is also allowed)
8 15
Run Code Online (Sandbox Code Playgroud)
我想要的是计算所有这些范围内坐标的出现次数.因此,对于上面的示例,输出将是这样的:
position count
1 1
2 1
3 2
4 3
5 3
6 2
7 3
8 3
9 3
10 3
11 2
12 2
13 1
14 1
15 1
Run Code Online (Sandbox Code Playgroud)
我有62000多个这样的范围,每个范围至少有1000个位置.我知道如何进行这种转换,但我不知道如何有效地做到这一点,即几秒钟.
当前(效率低下的代码)
positions <- c()
for(i in seq(nrow(a))){
positions <- c(positions, seq(a[i,3], a[i,4]))
}
table(positions)
Run Code Online (Sandbox Code Playgroud)
"a"是我的数据框,开始和结束坐标分别在第三和第四列.
数据框中的一列包含字符,因此对于使用apply我要么需要创建一个新的数据框(消耗额外的空间),要么需要在apply函数内转换为整数(额外的时间).对不起,因为之前没有告知此事.
对于一个非常快速的代码,data.table请参阅docendo discimus
(+ benchmark)的答案
以下是其他一些解决方案的基准:
set.seed(42)
N <- 1000
df <- data.frame(start=sample.int(10*N, N))
df$end <- df$start + sample(3:20, N, rep=TRUE)
library("microbenchmark")
microbenchmark(unit = "relative",
ori = { positions <- c()
for(i in seq(nrow(df))){
positions <- c(positions, seq(df[i,1], df[i,2]))
}
table(positions) },
a = table(unlist(apply(df, 1, function(x) x[1]:x[2]))), # my solution, similar: KenS, EricSchutte
m1 = table(unlist(mapply(seq, df$start, df$end))), # my variant of Sotos' solution
m2 = table(unlist(mapply(':', df$start, df$end))), # my variant of Sotos' solution
M1 = table(unlist(Map(seq, df$start, df$end))), # my variant of Sotos' solution
M2 = table(unlist(Map(':', df$start, df$end))), # Sotos
l = table(unlist(lapply(seq_len(nrow(df)), function(i) seq(df$start[i], df$end[i])))), # lmo
t = { temp <- unlist(lapply(seq_len(nrow(df)), function(i) seq(df$start[i], df$end[i]))) # lmo tabulate()
cbind(sort(unique(temp)), tabulate(temp)) },
d = table(do.call(c, mapply(seq, df$start, df$end))), # @989 (comment to the answer from Sotos)
dd = table(do.call(c, mapply(seq.int, df$start, df$end))), # docendo discimus (comment to this answer)
f = { pos <- data.frame(x=(min(df):max(df)),n=0) # Andrew Gustar
for(i in seq_along(df$start)){
low=min(df$start[i])-pos$x[1]+1
high=max(df$end[i])-pos$x[1]+1
pos$n[low:high] <- pos$n[low:high]+1
} }
)
# Unit: relative
# expr min lq mean median uq max neval cld
# ori 7.163767 7.219099 7.573688 7.379160 7.912435 7.899586 100 e
# a 1.194627 1.194855 1.211432 1.209485 1.213118 1.711994 100 a
# m1 1.645659 1.660294 1.711141 1.686973 1.710461 2.217141 100 b
# m2 1.005302 1.007125 1.017115 1.009618 1.017207 1.576201 100 a
# M1 1.642688 1.645174 1.733173 1.673924 1.686253 2.218028 100 b
# M2 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100 a
# l 3.487924 3.512732 3.801530 3.665725 4.188701 4.216375 100 d
# t 2.670636 2.711345 2.961449 2.869190 3.066150 3.745984 100 c
# d 1.652376 1.650798 1.721377 1.665901 1.712064 2.187129 100 b
# dd 1.040941 1.045652 1.060601 1.047534 1.053305 1.592163 100 a
# f 8.287098 8.486854 9.052884 9.046376 9.126318 25.210722 100 f
Run Code Online (Sandbox Code Playgroud)
解决方案tabulate()产生警告.
一个想法,
as.data.frame(table(unlist(Map(`:`, df$start, df$end))))
# Var1 Freq
#1 1 1
#2 2 1
#3 3 2
#4 4 3
#5 5 3
#6 6 2
#7 7 3
#8 8 3
#9 9 3
#10 10 3
#11 11 2
#12 12 2
#13 13 1
#14 14 1
#15 15 1
Run Code Online (Sandbox Code Playgroud)