我有一个带坐标的数据框("开始","结束")和标签(" group"):
a <- data.frame(start=1:4, end=3:6, group=c("A","B","C","D"))
a
start end group
1 1 3 A
2 2 4 B
3 3 5 C
4 4 6 D
我想创建一个新的数据框,其中标签被分配给坐标范围内序列的每个元素:
V1 V2
1 1 A
2 2 A
3 3 A
4 2 B
5 3 B
6 4 B
7 3 C
8 4 C
9 5 C
10 4 D
11 5 D
12 6 D
以下代码可以正常工作,但是范围很宽:
df<-data.frame()
for(i in 1:dim(a)[1]){
s<-seq(a[i,1],a[i,2])
df<-rbind(df,data.frame(s,rep(a[i,3],length(s))))
}
colnames(df)<-c("V1","V2")
如何加快速度?
答案 0 :(得分:4)
您可以尝试 data.table
library(data.table)
setDT(a)[, start:end, by = group]
给出了
group V1
1: A 1
2: A 2
3: A 3
4: B 2
5: B 3
6: B 4
7: C 3
8: C 4
9: C 5
10: D 4
11: D 5
12: D 6
显然,只有当你每组有一行时才会这样做,这似乎你在这里。
答案 1 :(得分:1)
如果您想在基础R中使用非常快速的解决方案,可以分两步手动创建data.frame
:
mapply
创建范围从“开始”到“结束”的list
。rep
+ lengths
将“groups”列重复为预期的行数。此处共享的基本R方法不依赖于每组只有一行。
尝试:
temp <- mapply(":", a[["start"]], a[["end"]], SIMPLIFY = FALSE)
data.frame(group = rep(a[["group"]], lengths(temp)),
values = unlist(temp, use.names = FALSE))
如果你做了很多,只需把它放在一个函数中:
myFun <- function(indf) {
temp <- mapply(":", indf[["start"]], indf[["end"]], SIMPLIFY = FALSE)
data.frame(group = rep(indf[["group"]], lengths(temp)),
values = unlist(temp, use.names = FALSE))
}
然后,如果您想要一些样本数据,可以使用以下作为样本数据:
set.seed(1)
a <- data.frame(start=1:4, end=sample(5:10, 4, TRUE), group=c("A","B","C","D"))
x <- do.call(rbind, replicate(1000, a, FALSE))
y <- do.call(rbind, replicate(100, x, FALSE))
请注意,随着“group”中不同唯一值的数量增加,这似乎会变慢。
(换句话说,“data.table”方法通常是最有意义的。我只是分享一个可能的基本R替代方案,它应该比现有方法快得多。)