Группы случайной выборки с последующей выборкой внутри этих групп выборки - PullRequest
0 голосов
/ 15 февраля 2020

Мой набор данных содержит несколько групп, и каждая группа может иметь различное количество уникальных наблюдений. Я выполняю некоторые расчеты по группам (упрощенно в коде ниже), в результате чего получаем итоговое значение для каждой группы. Далее, для целей bootstrap я хочу:

  1. Произвольная выборка групп с заменой (количество групп выборок = равно количеству различных групп в исходном наборе данных)
  2. Внутри этих выборочных групп случайные выборочные наблюдения с заменой (количество выборочных наблюдений на группу = равно числу уникальных наблюдений в этой группе в исходном наборе данных)

Упрощенная версия моих данных set up (data1):

data1:

id    group  y
1001  1      10
1002  1      15
1003  1      3
3002  2      24
3003  2      15
3005  2      37
3006  2      32
3007  2      11
4001  3      12
4002  3      15
5006  4      7
5007  4      9
5009  4      22
5010  4      19

Например, на основе приведенного выше примера набора данных: в исходном наборе данных 4 группы, поэтому я хочу выбрать 4 группы с заменой (например, группы выборок = группы 4,3 , 3,1), а затем выборочные наблюдения / строки из этих 4 групп (4 идентификатора из группы 4 (например, 5007, 5007, 5006, 5009); 2 идентификатора из группы 3 (дважды, поскольку группа 3 была отобрана дважды), и 3 идентификатора из группы 1 (все с заменой) и возвращение выбранных строк вместе в кадре данных (4 + 2 + 2 + 3 = 11 строк).

Что касается выше, у меня есть код, работающий для шаги по отдельности, но я не могу объединить их:

# Calculate group value
y.group <- tapply(data1$y,data1$group,mean)

# Step 1. Sample groups, with replacement:
sampled.group <- sample(1:length(unique(data1$group)),replace=T)

# Step 2. Sample within groups, with replacement
data2 <- data.frame(data1 %>%
   group_by(group) %>%   # for each group
   sample_frac(1, replace = TRUE) %>%
   ungroup)

Очевидно, что приведенный выше код полностью не выполняет то, что я хочу, так как в шаге 2 выборочные группы из шага 1 игнорируются поскольку он просто использует исходную группу var (я знаю об этом) . Я попытался решить эту проблему, используя шаг 1 и пытаясь сгенерировать новый фрейм данных, содержащий только наблюдения групп выборок (с дубликатами, если группа была выбрана более одного раза, что может произойти), а затем применить шаг 2 к этому новому датафрейм, но я не могу заставить это работать.

Я думаю, что я просто на неверном пути или слишком много думаю. Надеюсь, вы можете дать мне несколько советов о том, как действовать.

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

total.result <- c()
for (j in 1:length(unique(data1$group))){
     sampled.group <- sample(1:length(unique(data1$group)),size=1,replace=T)
     group.result <- sample_n(data1[data1$group==sampled.group,],
            size=length(unique(data1$id[data1$group==sampled.group])),replace=T)
     total.result <- rbind(total.result,group.result)
     }

(Таким образом, в основном используется al oop для выборки групп по одной, создания наборов данных для каждой, а затем выборки отдельных строк из них и, наконец, объединения результатов с rbind)

Однако я думаю, Решение Аллана Кэмерона (см. Ниже) более прямолинейно, поэтому я принял это как ответ на мой вопрос.

1 Ответ

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

Я думаю, это то, что вы ищете. Давайте начнем с ваших данных в воспроизводимом формате:

data1 <- structure(list(id = structure(1:14, .Label = c("1001", "1002", 
"1003", "3002", "3003", "3005", "3006", "3007", "4001", "4002", 
"5006", "5007", "5009", "5010"), class = "factor"), group = structure(c(1L, 
1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 4L, 4L, 4L, 4L), .Label = c("1", 
"2", "3", "4"), class = "factor"), y = structure(c(1L, 4L, 8L, 
7L, 4L, 10L, 9L, 2L, 3L, 4L, 11L, 12L, 6L, 5L), .Label = c("10", 
"11", "12", "15", "19", "22", "24", "3", "32", "37", "7", "9"
), class = "factor")), class = "data.frame", row.names = c(NA, 
-14L))

И просто чтобы убедиться:

data1
#>      id group  y
#> 1  1001     1 10
#> 2  1002     1 15
#> 3  1003     1  3
#> 4  3002     2 24
#> 5  3003     2 15
#> 6  3005     2 37
#> 7  3006     2 32
#> 8  3007     2 11
#> 9  4001     3 12
#> 10 4002     3 15
#> 11 5006     4  7
#> 12 5007     4  9
#> 13 5009     4 22
#> 14 5010     4 19

Мы начнем с разделения фрейма данных на group на меньшие фреймы данных, используя функцию split. Это дает нам список с четырьмя фреймами данных, каждый из которых содержит всех членов своей соответствующей группы. (set.seed предназначен только для того, чтобы сделать этот пример воспроизводимым).

set.seed(69)
split_dfs <- split(data1, data1$group)

Теперь мы можем сэмплировать этот список, дав нам новый список из четырех фреймов данных, составленных с заменой из split_dfs. Каждый из них снова будет содержать всех членов своей соответствующей группы, хотя, конечно, некоторые целые группы могут быть взяты несколько раз, а другие целые группы вообще не отобраны.

sampled_group_dfs <- split_dfs[sample(length(split_dfs), replace = TRUE)]

Теперь мы можем сделать выборку в пределах каждой группы путем выборки с заменой из строк каждого фрейма данных в нашем новом списке. Мы делаем это для всех наших фреймов данных в нашем списке, используя lapply

all_sampled <- lapply(sampled_group_dfs, function(x) x[sample(nrow(x), replace = TRUE), ])

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

result <- do.call(rbind, all_sampled)

Как видно из конечного результата, так получилось, что каждая из четырех групп была выбрана один раз (это случайно - измените set.seed, чтобы получить разные результаты). Тем не менее, внутри групп явно были нарисованы дубликаты. Фактически, поскольку R предписывает уникальные имена строк во фрейме данных, их легко выбрать с помощью .1, добавленного к дублирующимся именам строк. Если вам это не нравится, вы можете сбросить имена строк с помощью rownames(result) <- seq(nrow(result))

result
#>          id group  y
#> 4.14   5010     4 19
#> 4.14.1 5010     4 19
#> 4.11   5006     4  7
#> 4.13   5009     4 22
#> 1.3    1003     1  3
#> 1.3.1  1003     1  3
#> 1.2    1002     1 15
#> 3.9    4001     3 12
#> 3.9.1  4001     3 12
#> 2.5    3003     2 15
#> 2.5.1  3003     2 15
#> 2.6    3005     2 37
#> 2.7    3006     2 32
#> 2.5.2  3003     2 15

, созданных в 2020-02-15 с помощью пакета prex (v0. 3,0)

...