R:将已排序的数字输入合并到区间

R:将已排序的数字输入合并到区间,r,R,我有一个排序的数字输入,如下所示: 1 1 10 1 12 18 1 16 30 1 30 40 2 35 45 DF = structure(list(V1 = c(1L, 1L, 1L, 1L, 2L), V2 = c(1L, 12L, 16L, 30L, 35L), V3 = c(10L, 18L, 30L, 40L, 45L)), .Names = c("V1", "V2", "V3"), row.names = c(NA, -5

我有一个排序的数字输入,如下所示:

1    1    10
1    12   18
1    16   30
1    30   40
2    35   45

DF = structure(list(V1 = c(1L, 1L, 1L, 1L, 2L), V2 = c(1L, 12L, 16L, 
30L, 35L), V3 = c(10L, 18L, 30L, 40L, 45L)), .Names = c("V1", 
"V2", "V3"), row.names = c(NA, -5L), class = "data.frame")
它按第一列和第二列排序。现在我正试图在R中设计一个高效的函数(高效,因为我的输入是数十万行),它可以合并重叠的行,例如,第2行和第3行在三个位置(16、17和18)重叠,而第3行和第4行在一个位置(30)重叠,而第5行以2开头,因此它与其他行分开。总之,我想得到:

1    1    10
1    12   40 
2    35   45 
1    1    40
2    35   45
但是,我正在努力合并一个参数,该参数表示“如果两行彼此足够接近,例如,在5个单位内),则合并它们,否则不合并。在这种情况下,我希望得到:

1    1    10
1    12   40 
2    35   45 
1    1    40
2    35   45
因为12-10=2<5。但如果参数设置为1,则输出将仅为原始值:

1    1    10
1    12   40 
2    35   45 
这里有一个方法:

library(data.table)
setDT(DT)

th = 5
DT[, g := cumsum(V2 - shift(V3, fill = first(V2)) >= th), by=V1]
DT[, .(V2 = first(V2), V3 = last(V3)), by=.(V1, g = rleid(V1, g))]

#    V1 g V2 V3
# 1:  1 1  1 40
# 2:  2 2 35 45

# same code with th = 1

#    V1 g V2 V3
# 1:  1 1  1 10
# 2:  1 2 12 40
# 3:  2 3 35 45

这适用于您的玩具示例

df <- data.frame(ID=c(1,1,1,1,2),
             X1=c(1,12,16,30,35),
             X2=c(10,18,30,40,45))

df %>% 
  group_by(ID) %>%                                  # group wise operation by ID
  mutate(lg=lag(X2+5,default=head(X2,1))) %>%     # for comparison, offset X2 column by +1 row and add value of 5
  mutate(lt=lg<=X2) %>%                           # check if lg <= X2 
  mutate(group=cumsum(lt != lag(lt,default=head(lt,1)))) %>%    # make groups based on logical test in lt
  group_by(ID,group) %>%
  summarise(X1=min(X1), X2=max(X2))               # summarise data as min and max of X1 and X2 respectively

我想你可以用一系列的突变来做一个
mutate
调用。当然你是对的。我分步列出它们以使它更容易理解。这是数据表动词的一个优点。我注意到…它似乎更简洁,什么是
setDT(DT)
,我得到了
错误:找不到符号DT
。你的意思是
setDT(DF)
?@战舰哦,是的,如果你在我所有
DT
的地方都使用
DF
,它应该可以工作。或者,你可以编写
DT=data.table(DF)
并跳过
setDT
步骤(它只是将一个data.frame转换成data.table)。奇怪的是,
setDT(DF)
DT=data.table(DF)
,和
DT=as.data.table(DF)
setDT(DF)
似乎是最有效的,因为它通过引用来更改输入,所以不会进行复制,对吗?@crainer是的。
setDT(DF)
将改变
DF
的位置,这与大多数没有“副作用”的R函数不同。其他两个选项将创建一个新对象
DT
,只保留
DF
;对于大多数输入,它们应该是相同的,但是它们的文档(
?as.data.table
?data.table
)可能会掩盖任何细微的差异。