我有一个列名为sorted_no
的数据框,如下所示
x_n$sorted_no
1 2 NA 3 4 NA NA NA NA NA NA NA 5 NA NA NA NA 6 NA NA NA NA NA 7
我希望此列中的NA
值的起始和结束索引如下所示
start end
2 4
5 13
13 18
18 24
答案 0 :(得分:4)
在基地R
:
vec <- scan(text="1 2 NA 3 4 NA NA NA NA NA NA NA 5 NA NA NA NA 6 NA NA NA NA NA 7", what=numeric())
diff_vec <- diff(is.na(c(0,vec)))
# [1] 0 0 1 -1 0 1 0 0 0 0 0 0 -1 1 0 0 0
# [18] -1 1 0 0 0 0 -1
data.frame(start= which(diff_vec==1)-1,
end= which(diff_vec==-1))
# start end
# 1 2 4
# 2 5 13
# 3 13 18
# 4 18 24
0
中的c(0,vec)
有助于我们确保不会以NA
data.table::rleid
和tapply
的另一种解决方案:
library(data.table)
do.call(rbind,
tapply(seq_along(vec)[is.na(vec)],rleid(vec)[is.na(vec)],
function(x) data.frame(start=min(x)-1,end=max(x)+1)))
# start end
# 3 2 4
# 6 5 13
# 8 13 18
# 10 18 24
在这里,我使用rleid
创建群组,seq_along
创建索引,在这些群组中,我使用min
和max
索引。
使用rle
的基础解决方案:
vec[is.na(vec)] <- Inf
rle_ <- rle(vec)
cumsum_ <- cumsum(rle_$lengths)
infs_ <- which(rle_$value == Inf)
data.frame(start = c(0,cumsum_)[infs_], end = cumsum_[infs_]+1)
# start end
# 1 2 4
# 2 5 13
# 3 13 18
# 4 18 24
base::rle
对NAs
给予特殊处理,而data.table::rleid
没有,因此我使用Inf
,使其不那么健壮。
答案 1 :(得分:0)
data.table解决方案:
数据:
x<-scan(text="1 2 NA 3 4 NA NA NA NA NA NA NA 5 NA NA NA NA 6 NA NA NA NA NA 7", what=numeric())
代码:
data.table(x,rleid(is.na(x)),seq_along(x))[is.na(x),.(start=V3[1]-1,end=V3[1]+.N),by=V2][,-1]
# start end
#1: 2 4
#2: 5 13
#3: 13 18
#4: 18 24
答案 2 :(得分:0)
另一个基础R解决方案:
which_na <- which(is.na(x_n$sorted_no))
which_notna <- which(!is.na(x_n$sorted_no))
data.frame(
start = intersect(which_na - 1L, which_notna),
end = intersect(which_na + 1L, which_notna)
)
start end
1 2 4
2 5 13
3 13 18
4 18 24
再一次,玩rle()(灵感来自Mudskipper):
r <- rle(is.na(x_n$sorted_no))
data.frame(
start = cumsum(r$lengths)[r$values] + 1,
end = head(cumsum(r$lengths)[!r$values], sum(r$values))
)