【问题标题】:r expand dataset with filled in datar 用填充的数据扩展数据集
【发布时间】:2020-08-23 10:02:15
【问题描述】:

我有一个包含 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,Possibility)

Probability列就是根据这个逻辑计算出来的。

  • 让我们从第一个数据集中的第 1 行和第 2 行开始。前两行 (1,2) 没有任何缺失数据,因此在预期输出中生成相同的两行,概率为 1。

  • 让我们看看原始数据集中的第 3 行。这在 X1 列中缺少值。因此在预期输出中生成了两行 3,4。因此概率为 0.5, 0.5。 1/2=0.5

  • 让我们看看原始数据集中的第 5 行。这包含 X2 和 X3 列中的缺失数据。所以这将在预期数据中生成 4 行,第 6、7、8.9 行。所以概率是0.25,0.25,0.25,0.25,1/4 = 0.25

  • 原始数据集的第 7 行缺少 x1、x2、x3 的值。所以这个场景将在预期的输出数据集中生成 8 行,第 11 行 - 第 18 行。因此概率为 0.125 , 1/8 = 0.125

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

【问题讨论】:

  • @akrun,这取决于每行缺失值的数量。例如,具有一个缺失值的行将在预期数据集中生成两行。具有 2 个缺失值的行将在预期数据集中生成 4 行,而具有所有缺失值的行将在预期数据集中生成 8 行?这能回答你的问题吗?
  • @akrun,啊,很抱歉造成混乱。
  • 你如何计算概率col
  • @VíctorCortés,好问题。我更新了我的问题,说明了如何估计概率。

标签: r dplyr apply reshape


【解决方案1】:

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

这里有两个功能:

  • 一个函数 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_row,并将probability 设置为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

【讨论】:

  • 感谢本。我会用不同的测试用例来测试这个逻辑
【解决方案2】:

我为使用expand.grid 的任何数字定义了{0,1} 组合的函数。对于等于0n,我使用了一维的data.frame 来避免没有NA 的行的复杂性。

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

现在我正在使用应用和替换函数来创建行列表。我使用来自dplyrmutate 创建概率列。

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)

【讨论】:

  • 这正是我所期待的,我还能够在列表中添加一些额外的列。谢谢犀牛
猜你喜欢
  • 1970-01-01
  • 2019-03-30
  • 1970-01-01
  • 2019-05-02
  • 1970-01-01
  • 1970-01-01
  • 2019-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多