R 按组(块)随机观察,无需替换

R 按组(块)随机观察,无需替换,r,dplyr,R,Dplyr,这是一个很好的例子。上一个问题的答案是随机抽样替换。如何更改代码,以便在不将观察结果放回“抽签”的情况下,将每个观察结果分配给“urn”的on 这是我现在掌握的代码: 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

这是一个很好的例子。上一个问题的答案是随机抽样替换。如何更改代码,以便在不将观察结果放回“抽签”的情况下,将每个观察结果分配给“urn”的on

这是我现在掌握的代码:

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)
set.seed(9782)

I此解决方案基于@Frank的评论。我创建了一个函数,对block
j
进行随机化,另一个函数为每个block调用该函数

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)
randomize_block无需替换,如下所示:


block_rand <-  as.tibble(randomizr::block_ra(blocks = df$group, conditions = c("urn_1","urn_2","urn_3")))

df2 <- as.tibble(bind_cols(df, block_rand))

df2 %>% janitor::tabyl(group, value) 

df2 %>%
  group_by(id) %>% 
  filter(n()>1) %>%
  str()

布洛克兰特%
分组依据(id)%>%
过滤器(n()>1)%>%
str()

在最后一个调用中
groups=J=3
但是您使用
g=10
组创建了
df
df%>%groupby(group)%%>%mutate(sample\u size=n())
将显示您在列表中要求每组有多少个样本mutate@eddi我只是补充了一点澄清。希望它能让我的目标变得清晰。
sample(rep(seq_-along(J),p*I))
如果你的
p*I
不是整数值的话,那么需要进行特殊处理。假设我有N=20个人,我希望他们分成/分区/分配到p=c(.25,.5,.25)大小的组。在这种情况下,我需要创建一个赋值向量,第一个组有.25*20=5个条目,第二个组有10个条目,第三个组有5个条目,比如
a0=rep(seq_-along(p),N*p)
。现在,我将通过排列使这些赋值随机:
a=sample(a0)
看起来不错。我可能会像
random_partition=function(p,N){Np那样做