r развернуть набор данных заполненными данными - PullRequest
2 голосов
/ 08 мая 2020

У меня есть набор данных с 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 рассчитывается на основе этого logi c.

  • Давайте начнем со строк 1 и 2 в 1-м наборе данных. В первых двух строках (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. Но мне интересно, есть ли какой-нибудь более хитрый и менее беспорядочный способ добиться этого. Спасибо.

Ответы [ 2 ]

1 голос
/ 08 мая 2020

Это можно упростить, но дайте мне знать, если это ближе к тому, что вам нужно.

Здесь 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_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
1 голос
/ 08 мая 2020

Я определил функцию для комбинаций {0,1} для любых чисел, используя expand.grid. Для n, равного 0, я использовал data.frame с 1 измерением, чтобы избежать сложностей для строк без NA.

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

Теперь я использую функцию apply и replace для создания списка ряды. Я использовал mutate из dplyr для создания столбца вероятности.

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)
...