В R, как я могу случайным образом выбрать два из трех имен 500 раз, со сбалансированным выбором?

#r #random #database-design

#r #Случайный #проектирование базы данных

Вопрос:

Я знаю, что могу использовать complete_ra из пакета randomizr для случайного и равного распределения по одному из трех «плеч» (в данном случае «руки» — это просто имена людей)

 library(randomizr)
set.seed(100)
names <- complete_ra(N = 500, num_arms = 3) 
#each "arm" is chosen ~167 times

#Now put the names in
library(plyr)
df <- transform(df,
            names=revalue(names,c("T1"="Luis", "T2"="Conor","T3"="Dafydd")))
  

Но что мне нужно, так это фактически назначить 500 выборок случайно выбранным двум из трех имен. Итак, мне нужно, чтобы мой набор данных был:

 ID#  Name1   Name2
1   Conor    Luis
2   Conor    Dafydd
3   Luis     Dafydd
...
500 Conor    Luis
  

и в конце мне нужно, чтобы каждое из 3-х было выбрано в равном количестве.

Обходной путь заключается в том, что, поскольку есть 3 имени, это означает, что есть и 3 комбинации, поэтому я мог бы просто заменить Конора на «Конор и Луис», Луиса на «Луис и Дэффид», а Дэффида на «Конор и Дэффид» … но я уверен, что есть более красноречивый способ, который допускал бы другие комбинации (например, выбор 2 из 4 имен). Также мне не нравится обходной путь, потому что в настоящее время каждое имя может отображаться, например, 8 раз подряд, что означает, что у нас будет точная пара 8 раз подряд. Я думаю, что более красноречивый метод случайного выбора 2 из 3 имен привел бы к меньшему количеству случаев «подряд».

Ответ №1:

Канонический способ выбора n элементов из списка (без замены здесь) был бы sample . Вот простой способ создать 500 таких выборок и преобразовать результат в data.frame :

 set.seed(100)
names <- c("Luis", "Conor", "Dafydd")
samples <- lapply(1:500, function(x) sample(names, 2))
head(as.data.frame(matrix(unlist(samples), ncol = 2, byrow = TRUE)))
#>       V1     V2
#> 1   Luis Dafydd
#> 2  Conor   Luis
#> 3  Conor   Luis
#> 4 Dafydd   Luis
#> 5  Conor   Luis
#> 6  Conor Dafydd
  

Создано 2019-03-15 пакетом reprex (версия 0.2.1)

Ответ №2:

Вот забавный подход с randomizr и tidyverse . Он рассматривает каждого человека как блок из двух наблюдений, затем использует pivot_wider для изменения формы данных

 library(tidyverse)
library(randomizr)

tibble(
  person_id = rep(1:500, each = 2),
  name = rep(c("Name1", "Name2"), 500),
  assignment = block_ra(
    blocks = person_id,
    conditions = c("Luis", "Conor", "Dafydd")
  )
) %>%
  pivot_wider(names_from = name,
              values_from = assignment)
#> # A tibble: 500 x 3
#>    person_id Name1  Name2 
#>        <int> <fct>  <fct> 
#>  1         1 Luis   Dafydd
#>  2         2 Conor  Luis  
#>  3         3 Dafydd Luis  
#>  4         4 Dafydd Conor 
#>  5         5 Conor  Dafydd
#>  6         6 Luis   Dafydd
#>  7         7 Dafydd Luis  
#>  8         8 Conor  Luis  
#>  9         9 Conor  Luis  
#> 10        10 Dafydd Conor 
#> # … with 490 more rows
  

Создано 2020-01-24 пакетом reprex (версия 0.3.0)