在矢量中生成随机长度NA的随机序列

age*_*nis 10 random r vector missing-data seq

我想在向量中生成缺失值,以便将缺失值按顺序分组,以模拟不同长度的缺失数据的时段.

假设我有一个10 000个值的向量,我想在向量中的随机位置生成12个NA序列,每个序列的随机长度L在1到144之间(144个模拟在时间步长10分钟时缺失值为2天).序列不得重叠.

我怎样才能做到这一点?谢谢.

我试过结合lapply而seq没有成功.

具有3个不同序列的预期输出示例:

# 1 2 3 5 2 NA NA 5 4 6 8 9 10 11 NA NA NA NA NA NA 5 2 NA NA NA...
Run Code Online (Sandbox Code Playgroud)

编辑

我正在处理季节性时间序列,因此NA必须覆盖值而不是作为新元素插入.

tal*_*lat 6

如果每个NA序列的起始位置和游程长度都应该是随机的,我认为你不能确定立即找到一个合适的解决方案,因为你的约束是序列不能重叠.

因此,我提出了以下解决方案,其尝试有限次数(max_iter)以找到起始位置和NA运行长度的拟合组合.如果找到一个,则返回它,如果在定义的最大迭代次数内没有找到,则只返回通知.

x = 1:1000
n = 3
m = 1:144

f <- function(x, n, m, max_iter = 100) {
  i = 0
  repeat {
    i = i+1
    idx <- sort(sample(seq_along(x), n))        # starting positions
    dist <- diff(c(idx, length(x)))             # check distance inbetween 
    na_len <- sample(m, n, replace = TRUE) - 1L # lengths of NA-runs
    ok <- all(na_len < dist)                    # check overlap
    if(ok | i == max_iter) break 
  }

  if(ok) {
    replace(x, unlist(Map(":", idx, idx+na_len)), NA)
  } else {
      cat("no solution found in", max_iter, "iterations")
    }
}

f(x, n, m, max_iter = 20)
Run Code Online (Sandbox Code Playgroud)

当然,您可以轻松地增加迭代次数,您应该注意到,越大越n难以找到解决方案(需要更多迭代).


李哲源*_*李哲源 5

所有其他答案或多或少都遵循"条件规范",其中模拟NA块的起始索引和运行长度.然而,由于必须满足非重叠条件,因此必须逐个确定这些块.这种依赖性禁止矢量化,并且必须使用for循环或lapply / sapply必须使用.

但是,这个问题只是另一个运行长度问题.12个不重叠的NA块将整个序列划分为13个非丢失的块(是的,我猜这是OP想要的,因为丢失的块发生在第一个块或最后一个块不感兴趣).那么为什么不考虑以下几点:

  • 生成12个丢失块的运行长度;
  • 生成13个非缺失块的运行长度;
  • 交错这两种类型的块.

第二步看起来很困难,因为它必须满足所有块的长度总和达到固定数量.好吧,多项分布仅适用于此.

所以这是一个完全矢量化的解决方案:

# run length of 12 missing chunks, with feasible length between 1 and 144
k <- sample.int(144, 12, TRUE)

# run length of 13 non-missing chunks, summing up to `10000 - sum(k)`
# equal probability is used as an example, you may try something else
m <- c(rmultinom(1, 10000 - sum(k), prob = rep.int(1, 13)))

# interleave `m` and `k`
n <- c(rbind(m[1:12], k), m[13])

# reference value: 1 for non-missing and NA for missing, and interleave them
ref <- c(rep.int(c(1, NA), 12), 1)

# an initial vector
vec <- rep.int(ref, n)

# missing index
miss <- is.na(vec)
Run Code Online (Sandbox Code Playgroud)

我们可以验证sum(n)是10000.下一步是什么?可以随意用随机整数填写非缺失条目吗?


我的初步答案可能太短,无法遵循,因此采取了上述扩展.

使用用户输入编写实现上述功能的功能代替示例参数值12,144,10000是直截了当的.

注意,多项式的唯一潜在问题是,在一些不好的情况下prob,它可能会产生一些零.因此,一些NA块实际上会连接在一起.为了解决这个问题,一个强有力的检查是这样的:将所有0替换为1,并从中减去这种变化的膨胀max(m).


Moo*_*per 5

编辑:只是为了好玩这里是我的解决方案下面的更短的递归版本

add_nas <- function(v,n_seq = 12,min_l_seq = 1,max_l_seq = 144){
  insert_length  <- sample(min_l_seq:max_l_seq,1)
  insert_pos     <- sample(length(v)-insert_length,1)
  v <- v[-(insert_pos+(1:insert_length)-1)]
  if(n_seq > 1){v <- add_nas(v,n_seq-1,min_l_seq,max_l_seq)}
  append(v,rep(NA,insert_length),insert_pos-1)
}
Run Code Online (Sandbox Code Playgroud)

老答案:

# we build a vextor of 20 values
v <- sample(1:100,20,replace=TRUE) # your vector
# your parameters
n_seq <- 3     # you put 12 here
min_l_seq <- 1 #
max_l_seq <- 5 # you put 144 here

# first we will delete items, then we add NAs where we deleted instead
insert_lengths <- sample(min_l_seq:max_l_seq,n_seq,replace=TRUE)
lengths_before_deletion <- length(v)- c(0,insert_lengths[-length(insert_lengths)])
insert_pos <- sapply(lengths_before_deletion-insert_lengths+1,function(x){sample(1:x,1)})

v2 <- v
print(v)
for (i in 1:n_seq){
  v2 <- v2[-(insert_pos[i]:(insert_pos[i]+insert_lengths[i]-1))]
  print(v2)
}

for (i in n_seq:1){
  v2 <- c(v2[1:(insert_pos[i]-1)],rep(NA,insert_lengths[i]),v2[insert_pos[i]:length(v2)])
  print(v2)
}
Run Code Online (Sandbox Code Playgroud)

这是日志

> print(v)
 [1] 75 11  4 19 55 20 65 48 85 20 61 16 75 31 50 10 30 61  4 32
> for (i in 1:n_seq){
+   v2 <- v2[-(insert_pos[i]:(insert_pos[i]+insert_lengths[i]-1))]
+   print(v2)
+ }
 [1] 75 11 55 20 65 48 85 20 61 16 75 31 50 10 30 61  4 32
 [1] 75 11 55 20 65 48 85 20 61 16 75 50 10 30 61  4 32
 [1] 75 11 55 20 65 48 85 20 61 16 75 50 10 30 32
> 
> for (i in n_seq:1){
+   v2 <- c(v2[1:(insert_pos[i]-1)],rep(NA,insert_lengths[i]),v2[insert_pos[i]:length(v2)])
+   print(v2)
+ }
 [1] 75 11 55 20 65 48 85 20 61 16 75 50 10 30 NA NA 32
 [1] 75 11 55 20 65 48 85 20 61 16 75 NA 50 10 30 NA NA 32
 [1] 75 11 NA NA 55 20 65 48 85 20 61 16 75 NA 50 10 30 NA NA 32
Run Code Online (Sandbox Code Playgroud)