如何使用R将整数向量有效折叠到序列的data.table中?

给出一个大向量。例如:

set.seed(1)
in_vec <- sample(1:10000,5000,replace = F)

如何有效地将其折叠到一个数据表中,该数据表提供所有连续整数的开始和结束坐标。我目前正在使用以下代码:

in_vec <- sort(in_vec) # sort by sequence
library(data.table)
interval_id <- findInterval(in_vec,in_vec[which(c(1,diff(in_vec)) > 1)]) # add unique IDs for sequences
dt <- data.table(vec = in_vec,# make data.table
             int_id = interval_id)
long_to_short <- function(sub){ data.table(start = sub$vec[1],end = sub$vec[nrow(sub)]) } # custom function
library(plyr)
output <- ddply(dt,"int_id",long_to_short)
output$int_id <- NULL

但是,我将其应用到的向量非常大,因此我需要最大化性能。有data.table方法吗?任何帮助将不胜感激!

a9363001128honey 回答:如何使用R将整数向量有效折叠到序列的data.table中?

使用中的rleid()有帮助:

library(data.table)

set.seed(1)
dt <- data.table(in_vec = sample(1:10000,5000,replace = F)) 

dt[order(in_vec),.(start = min(in_vec),end = max(in_vec)),by = .(grp = rleid(c(0,cumsum(diff(in_vec) > 1))))
   ]

       grp start  end
   1:    1     4    4
   2:    2     6    7
   3:    3    14   16
   4:    4    19   19
   5:    5    26   27
  ---                
2483: 2483  9980 9980
2484: 2484  9988 9988
2485: 2485  9991 9992
2486: 2486  9994 9994
2487: 2487  9997 9998

对于完全基础的解决方案,这应该是性能最高的,因为它不是分组操作:

set.seed(1)
in_vec <- sample(1:10000,replace = F)
in_vec <- sort(in_vec)

grp <- c(0,cumsum(diff(in_vec) > 1))

data.frame(grp = unique(grp),start = in_vec[!duplicated(grp)],end = in_vec[!duplicated(grp,fromLast = T)]
)
,

像这样吗?

dt[,.(start = first(vec),end = last(vec)),int_id]

编辑:我想以下操作将在data.table中完成您需要的工作,根据值的实际范围调整fill = -1

set.seed(1)
in_vec <- sample(1:10000,replace = F)
dt <- data.table(vec = in_vec,key = 'vec')
dt[,int_id := cumsum(!shift(vec,1,fill = -1) == vec - 1)]
dt[,int_id]
,

您快到了,只需要使用已排序向量之间的差异来创建一个组。然后对它们进行瞄准。

set.seed(1)
in_vec <- sample(1:10000,replace = F)
in_vec <- sort(in_vec)
grps <- cumsum(c(1,diff(in_vec)>1))

output <- data.frame(do.call(rbind,tapply(in_vec,grps,range)))
names(output) <- c("start","end")

还有dplyr解决方案

set.seed(1)
in_vec <- sample(1:10000,replace = F)
data.frame(x=in_vec) %>% 
arrange(x) %>%
mutate(grps=cumsum(c(1,diff(x)>1))) %>%
group_by(grps) %>%
summarise(start=min(x),end=max(x)) %>%
select(start,end)
本文链接:https://www.f2er.com/3133074.html

大家都在问