В R с кластеризованными данными, как бы вы bootstrap на уровне кластера и сохранили те же наблюдения, когда кластеры выбираются повторно? - PullRequest
0 голосов
/ 26 февраля 2020

Я пытаюсь bootstrap сделать выборку в R из набора продольных данных с несколькими наблюдениями на человека (то есть данные, собранные в несколько волн во времени). Таким образом, данные выглядят так:

id     wave   variable
101    1      15
101    2      17
101    3      18
102    1      13
102    2      14
102    3      14
103    1      13
103    2      15
103    3      17

Я хотел бы сделать выборку на уровне ЧЕЛОВЕКА и оставить только одно наблюдение (волну) на человека, случайно выбранного, но сохранить то же наблюдение, если / когда человек отбирается несколько раз. Таким образом, пример bootstrap может выглядеть так:

id     wave   variable
101    1      15
103    2      15
101    1      15 

, но никогда не будет так:

id     wave   variable
101    1      15
103    2      15
101    2      17

Я борюсь с тем, как вообще это кодировать, тем более делать это элегантно. Любые мысли будут высоко ценится.

Ответы [ 3 ]

1 голос
/ 26 февраля 2020

Вы можете получить фрейм данных с одной строкой для каждого произвольно выбранного идентификатора, а затем просто отобрать этот фрейм данных с заменой:

set.seed(69)
dfs <- split(df, df$id)
dfs <- mapply(function(x, y) x[sample(y,1),], dfs, sapply(dfs, nrow), SIMPLIFY = FALSE)
result <- do.call(rbind, dfs)
result[sample(nrow(result), 9, TRUE), ]
#>        id wave variable
#> 101   101    1       15
#> 103   103    2       15
#> 103.1 103    2       15
#> 103.2 103    2       15
#> 102   102    3       14
#> 101.1 101    1       15
#> 103.3 103    2       15
#> 102.1 102    3       14
#> 102.2 102    3       14

Создано в 2020-02-26 с помощью представительный пакет (v0.3.0)

0 голосов
/ 26 февраля 2020

Мы могли бы сначала произвести выборку для каждого id одного из его wave значений, а затем inner_join исходных данных. Затем мы bootstrap сэмплируем из этого «отфильтрованного» списка ...

Создаем больший набор данных для воспроизведения сэмплирования:

set.seed(13)
df <- data.frame(id = rep(101:103, each=9),
                 wave = rep(1:3, times=9),
                 variable = sample(1:20,9*3, TRUE))

head(df)
   id wave variable
1 101    1        4
2 101    2        2
3 101    3        1
4 101    1       19
5 101    2       19
6 101    3       17

Решение с использованием dplyr:

library(dplyr)

  boot_size = 1000

boot <- df %>% 
  inner_join(df %>% 
               group_by(id, ) %>% 
               sample_n(1) %>% 
               select(id, wave)) %>% 
  sample_n(boot_size, replace = TRUE)

Проверьте работоспособность:

  head(boot)
   id wave variable
1 101    2        5
2 103    3        4
3 102    3       11
4 103    3        3
5 103    3        3
6 101    2        6
table(boot$id, boot$wave)
      2   3
101 323   0
102   0 353
103   0 324

Хорошо выглядит, каждый id имеет значения только из одного wave

Редактировать:

Я случайно разместил рабочую, но очень неэффективную и глупую версию решения, где мое соединение data.frame выбрано из всех комбинации id, wave И variable. Но нам не нужны все эти комбинации на этом этапе. Я поменял эту строку кода на менее глупую. К сожалению.

0 голосов
/ 26 февраля 2020

Ваш пример:

x = structure(list(id = c(101L, 101L, 101L, 102L, 102L, 102L, 103L, 
103L, 103L), wave = c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), variable = c(15L, 
17L, 18L, 13L, 14L, 14L, 13L, 15L, 17L)), class = "data.frame", row.names = c(NA, 
-9L))

Может быть, что-то вроде этого, если вы не возражаете, dplyr:

set.seed(111)
x %>% group_by(id) %>% sample_n(1) %>%  
ungroup() %>% sample_n(n(),replace=TRUE)

# A tibble: 3 x 3
     id  wave variable
  <int> <int>    <int>
1   103     3       17
2   101     2       17
3   103     3       17

В первой строке вы группируете по идентификатору, и образец 1 Далее вы разгруппируете, поэтому у вас есть только уникальные идентификаторы. Тогда это вопрос выборки этих строк с заменой. Надеюсь, я понял правильно.

...