2016-04-21 2 views
0

Это follow up question. Ответы в предыдущем вопросе делают случайную выборку с заменой. Как я могу изменить код, чтобы назначить каждое наблюдение на J «урну», не откладывая наблюдение в «лотерее»?случайные наблюдения по группам (блокам) без замены

Это код, я прямо сейчас:

set.seed(9782) 
I <- 500 
g <- 10 
library(dplyr) 

anon_id <- function(n = 1, lenght = 12) { 
    randomString <- c(1:n) 
    for (i in 1:n) 
    { 
    randomString[i] <- paste(sample(c(0:9, letters, LETTERS), 
            lenght, replace = TRUE), 
          collapse = "") 
    } 
    return(randomString) 
} 

df <- data.frame(id = anon_id(n = I, lenght = 16), 
       group = sample(1:g, I, T)) 

J <- 3 
p <- c(0.25, 0.5, 0.25) 

randomize <- function(data, urns=2, block_id = NULL, p=NULL, seed=9782) { 
    if(is.null(p)) p <- rep(1/urns, urns) 
    if(is.null(block_id)){ 
    df1 <- data %>% 
     mutate(Treatment = sample(x = c(1:urns), 
           size = n(), 
           replace = T, 
           prob = p)) 
    return(df1) 
    }else{ 
    df1 <- data %>% group_by_(block_id) %>% 
     mutate(Treatment = sample(x = c(1:urns), 
           size = n(), 
           replace = T, 
           prob = p)) 
    } 
}  

df1 <- randomize(data = df, urns = J, block_id = "group", p = p, seed = 9782) 

Если изменить replace = T к replace = F я получаю следующее сообщение об ошибке:

Error: cannot take a sample larger than the population when 'replace = FALSE' 

Разъяснение моей цели:

Предположим, что у меня есть 10 классных комнат (или деревень или что-то ли ke, что). Чтобы это было просто, предположите, что в каждом классе 20 учеников (в действительности у них будет N_j). Класс на класс, я хочу назначить каждого ученика одной из J-групп, например J=3. P указывает долю, которая будет назначена каждой группе. Например, 25% к группе 1 40% к группе 2 и 35% к группе 3.

+0

в последнем вызове 'groups = J = 3', но вы создали' df' с 'g = 10' группами? – jaimedash

+0

'df%>% group_by (group)%>% mutate (sample_size = n())' покажет вам, сколько выборок вы запрашиваете для каждой группы в мутате – jaimedash

+0

@jaimedash я использовал группы слов для ссылки на два разные вещи. Я обновил код, чтобы исправить это. У меня есть J = 3 'urns', и я хочу сделать случайное задание' group' – Ignacio

ответ

1

Это решение основано на комментарии @ Frank. Я создал одну функцию, которая выполняет рандомизацию для блока j, а другую, которая вызывает эту функцию для каждого блока.

randomize_block <- function(data, block=NULL, block_name=NULL, urns, p, seed=9782) { 
    set.seed(seed) 
    if(!is.null(block)) { 
    condition <- paste0(block_name,"==",block) 
    df <- data %>% filter_(condition) 
    } else df <- data 
    if(is.null(p)) p <- rep(1/urns, urns) 
    N <- nrow(df) 
    Np <- round(N*p,0) 
    if(sum(Np)!=N) Np[1] <- N - sum(Np[2:length(Np)]) 
    Urns = rep(seq_along(p), Np) 
    Urns = sample(Urns) 
    df$urn <- Urns 
    return(df) 
} 

randomize <- function(data, block_name=NULL, urns, p, seed=9782) { 
    if(is.null(p)) p <- rep(1/urns, urns) 
    if(!is.null(block_name)){ 
    blocks <- unique(data[,block_name]) 
    df <- lapply(blocks, randomize_block, 
       data = data, 
       block_name=block_name, 
       urns = urns, 
       p = p, 
       seed=seed) 
    return(data.table::rbindlist(df)) 
    }else { 
    df <- randomize_block(data = data, 
          urns = urns, p = p, 
          seed=seed) 
    } 
} 

test <- randomize(data = df, block_name = "group", 
        urns = 3, p = c(0.25, 0.5, 0.25), 
        seed=4222016) 

Я пытаюсь выяснить, если можно использовать dplyr сделать это, альтернативные решения, реализующие которые являются более чем приветствуется!

+1

Выглядит хорошо. Я, вероятно, сделаю это как «random_partition = function (p, N) {Np <- round (N * p); Np [1L] <- N - сумма (Np [-1L]); sample (rep (seq_along (p), Np))}; setDT (df) [, urn: = random_partition (p, .N), by = group] ' – Frank

Смежные вопросы