r 用填充的数据扩展数据集

r expand dataset with filled in data

我有一个包含 4 列的数据集。现在可以取 2 个值。(1 或 0)。三列 (X1, X2, X3) 缺少数据。

Row#    X1   X2   X3    Y
1       1    0    0     1
2       0    1    1     0 
3       NA   0    0     0
4       1    1    1     0
5       1    NA   NA    1
6       1    0    0     1
7       NA   NA   NA    0
8       0    1    0     1
9       NA   NA   1     0
10      0    0    1     1
11      NA   NA   0     0
12      0    0    0     0
13      0    0    1     1
14      NA   0    NA    0

我感兴趣的是为 NA 的可能值创建一个填充数据集。我的意思是创建可能的数据行,如下所示

Row#   X1  X2  X3  Y  Probability  Comments
1      1   0   0   1  1            No missing
2      0   1   1   0  1            No missing

3      1   0   0   0  0.5          X1 Missing
4      0   0   0   0  0.5          X1 Missing

5      1   1   1   0  1            No missing

6      1   1   0   1  0.25         X1, X2 missing 
7      1   0   0   1  0.25         X1, X2 missing 
8      1   1   1   1  0.25         X1, X2 missing 
9      1   0   1   1  0.25         X1, X2 missing 

10     1   0   0   1  1            No missing 

11     0   0   0   0  0.125        X1, X2, x3 missing 
12     1   0   0   0  0.125        X1, X2, x3 missing
13     0   1   0   0  0.125        X1, X2, x3 missing
14     0   0   1   0  0.125        X1, X2, x3 missing
15     1   1   0   0  0.125        X1, X2, x3 missing
16     1   0   1   0  0.125        X1, X2, x3 missing
17     0   1   1   0  0.125        X1, X2, x3 missing
18     1   1   1   0  0.125        X1, X2, x3 missing
19     .   .   .   .  .            ......
20     .   .   .   .  .            ......
21     .   .   .   .  .            ......
22     .   .   .   .  .            ......

请注意最终数据集将包含 5 列(X1、X2、X3、Y、可能性)

Probability列就是按照这个逻辑计算出来的。

我可以使用 8 个 ifelse 语句和 for 循环来做到这一点。但我想知道是否有更简单、更简单的方法来实现这一目标。谢谢。

我为使用 expand.grid 的任何数字定义了 {0,1} 组合的函数。对于等于 0n,我使用了具有 1 个维度的 data.frame 以避免没有 NA.

的行的复杂化
comb <- function(n) { 
    if(n==0) return(data.frame(Var1 = c(1)))
    expand.grid(rep(list(0:1),n)) 
}

现在我正在使用应用和替换函数来创建行列表。我使用 dplyr 中的 mutate 创建概率列。

df = apply(df, 1, function(v){
  NA_count = length(which(is.na(v)))
  apply(comb(NA_count) , 1 ,  FUN = replace , x = v, list = 
  which(is.na(v))) %>% 
  t %>% as.data.frame() %>%
  mutate( Probability = (1/2)^length(which(is.na(v))))
})

最后,我把所有的列表和do.call放在一起了。

do.call(rbind,df)

这可以简化 - 但如果这更接近您的需要,请告诉我。

这里有2个函数:

  • 一个函数make_mat(x, k)创建一个包含0和1的向量(例如,make_mat(7,4)0 1 1 1,它有4位长,二进制等于7 )

  • 第二个函数sub_mat将创建一个包含2^n_repl行的矩阵,其中n_repl是要替换的NA行数。

为原始数据框中的每一行创建一个列表。现在,计算列表的行数 num_rowprobability 设置为 1/num_row

make_mat <- function(x, k) {
  return(rev(as.integer(intToBits(x))[1:k]))
}

sub_mat <- function(x) {
  n_repl <- sum(+(is.na(x)))
  mat_repl <- t(sapply(1:2^n_repl-1, make_mat, k = n_repl))
  new_mat <- matrix(rep(x, 2^n_repl), ncol = length(x), byrow = T)
  new_mat[is.na(new_mat)] <- mat_repl
  new_mat
}

lst <- apply(df, 1, sub_mat)
num_row <- sapply(lst, nrow, simplify = T)
result <- as.data.frame(Reduce(rbind, Map(cbind, lst, 1/num_row)))
names(result) <- c(names(df), "probability")
result

输出

   X1 X2 X3 Y probability
1   1  0  0 1       1.000
2   0  1  1 0       1.000
3   0  0  0 0       0.500
4   1  0  0 0       0.500
5   1  1  1 0       1.000
6   1  0  0 1       0.250
7   1  0  1 1       0.250
8   1  1  0 1       0.250
9   1  1  1 1       0.250
10  1  0  0 1       1.000
11  0  0  0 0       0.125
12  0  0  1 0       0.125
13  0  1  0 0       0.125
14  0  1  1 0       0.125
15  1  0  0 0       0.125
16  1  0  1 0       0.125
17  1  1  0 0       0.125
18  1  1  1 0       0.125
19  0  1  0 1       1.000
20  0  0  1 0       0.250
21  0  1  1 0       0.250
22  1  0  1 0       0.250
23  1  1  1 0       0.250
24  0  0  1 1       1.000
25  0  0  0 0       0.250
26  0  1  0 0       0.250
27  1  0  0 0       0.250
28  1  1  0 0       0.250
29  0  0  0 0       1.000
30  0  0  1 1       1.000
31  0  0  0 0       0.250
32  0  0  1 0       0.250
33  1  0  0 0       0.250
34  1  0  1 0       0.250