给出部分排序的向量:
A <- c(1,1,1,1,1,0,0,0,0,0,2,2,2,2,2,-1,-1,-1,-1,-1)
目的是将该向量解构为一个表格,以显示这些表格的不同值和范围:
start end value
1 5 1
6 10 0
11 15 2
16 20 -1
我尝试使用diff函数,但似乎找不到找到将值聚集到所需范围内的好方法。
答案 0 :(得分:3)
使用rle()
(行程编码)
A <- c(1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2,
-1, -1, -1, -1, -1, 1, 1, 1, 0, 0, 0, 0)
rled <- as.data.frame(unclass(rle(A)))
rled$end <- cumsum(rled$lengths)
rled$start <- rled$end - rled$lengths + 1
rled[, c("start", "end", "values")]
# start end values
# 1 1 5 1
# 2 6 10 0
# 3 11 15 2
# 4 16 20 -1
# 5 21 23 1
# 6 24 27 0
答案 1 :(得分:2)
我们可以使用rleid
中的data.table
。我们遍历每个唯一编号,找到它在原始序列中的第一个和最后一个出现,然后将其转换为data.frame。
library(data.table)
indx <- rleid(A)
new_dat <- data.frame(t(sapply(unique(indx), function(x) {
val <- which(indx == x)
c(start = min(val), stop = max(val))
})))
transform(new_dat, value = A[new_dat$start])
# X1 X2 value
#1 1 5 1
#2 6 10 0
#3 11 15 2
#4 16 20 -1
当数字重复时
A <- c(1,1,1,1,1,0,0,0,0,0,2,2,2,2,2,-1,-1,-1,-1,-1, 1, 1, 1)
indx <- rleid(A)
new_dat <- data.frame(t(sapply(unique(indx), function(x) {
val <- which(indx == x)
c(start = min(val), stop = max(val))
})))
transform(new_dat, value = A[new_dat$start])
# start stop value
#1 1 5 1
#2 6 10 0
#3 11 15 2
#4 16 20 -1
#5 21 23 1
@Henrik建议的一种更简洁的data.table
方式
library(data.table)
data.table(A)[ , .(from = .I[1], to = .I[.N], val = A[1]), by = rleid(A)][,-1]
# from to val
#1: 1 5 1
#2: 6 10 0
#3: 11 15 2
#4: 16 20 -1
#5: 21 23 1