代码之家  ›  专栏  ›  技术社区  ›  cliu

模拟不平衡的集群数据

  •  0
  • cliu  · 技术社区  · 5 年前

    我想模拟一些不平衡的集群数据。集群数量为20个,平均观测数量为30个。然而,我想为每个集群创建一个不平衡的集群数据,其中观察值比指定值多10%(即33而不是30)。然后,我想随机排除适当数量的观察值(即60),以获得每个簇的指定平均观察值(即30)。排除每个集群内的观察的概率并不一致(即,一些集群没有移除病例,而其他集群则被更多地排除)。因此,最后我总共还有600次观察。有人知道如何在R中实现这一点吗?下面是一个较小的示例数据集。不过,每个簇的观察次数并不符合上面指定的条件,我只是用这个来表达我的想法。

    > y <- rnorm(20)
    > x <- rnorm(20)
    > z <- rep(1:5, 4)
    > w <- rep(1:4, each=5)
    > df <- data.frame(id=z,cluster=w,x=x,y=y) #this is a balanced dataset
    > df
       id cluster           x           y
    1   1       1  0.30003855  0.65325768
    2   2       1 -1.00563626 -0.12270866
    3   3       1  0.01925927 -0.41367651
    4   4       1 -1.07742065 -2.64314895
    5   5       1  0.71270333 -0.09294102
    6   1       2  1.08477509  0.43028470
    7   2       2 -2.22498770  0.53539884
    8   3       2  1.23569346 -0.55527835
    9   4       2 -1.24104450  1.77950291
    10  5       2  0.45476927  0.28642442
    11  1       3  0.65990264  0.12631586
    12  2       3 -0.19988983  1.27226678
    13  3       3 -0.64511396 -0.71846622
    14  4       3  0.16532102 -0.45033862
    15  5       3  0.43881870  2.39745248
    16  1       4  0.88330282  0.01112919
    17  2       4 -2.05233698  1.63356842
    18  3       4 -1.63637927 -1.43850664
    19  4       4  1.43040234 -0.19051680
    20  5       4  1.04662885  0.37842390
    

    随机添加和删除一些数据后,不平衡的数据会变成这样:

                id   cluster   x     y
           1     1       1  0.895 -0.659 
           2     2       1 -0.160 -0.366 
           3     1       2 -0.528 -0.294 
           4     2       2 -0.919  0.362 
           5     3       2 -0.901 -0.467 
           6     1       3  0.275  0.134 
           7     2       3  0.423  0.534 
           8     3       3  0.929 -0.953 
           9     4       3  1.67   0.668 
          10     5       3  0.286  0.0872
          11     1       4 -0.373 -0.109 
          12     2       4  0.289  0.299 
          13     3       4 -1.43  -0.677 
          14     4       4 -0.884  1.70  
          15     5       4  1.12   0.386 
          16     1       5 -0.723  0.247 
          17     2       5  0.463 -2.59  
          18     3       5  0.234  0.893 
          19     4       5 -0.313 -1.96  
          20     5       5  0.848 -0.0613
    

    编辑 这部分问题已经解决(归功于jay.sf)。接下来,我想重复这个过程1000次,并在每个生成的数据集上运行回归。但是,我不想在整个数据集上运行回归,而是在一些随机选择的集群上运行回归(可以使用此函数: df[unlist(cluster[sample.int(k, k, replace = TRUE)], use.names = TRUE), ] .最后,我想从这1000个回归中得到置信区间。如何进行?

    0 回复  |  直到 5 年前
        1
  •  1
  •   cliu    5 年前

    根据Ben Bolker的要求,我发布了我的解决方案,但见jay。sf提供了一个更概括的答案。

    #First create an oversampled dataset: 
      y <- rnorm(24)
      x <- rnorm(24)
      z <- rep(1:6, 4)
      w <- rep(1:4, each=6)
      df <- data.frame(id=z,cluster=w,x=x,y=y)
    #Then just slice_sample to arrive at the sample size as desired
      df %>% slice_sample(n = 20) %>%
      arrange(cluster)
    #Or just use base R
      a <- df[sample(nrow(df), 20), ]  
      df2 <- a[order(a$cluster), ]
    
        2
  •  0
  •   jay.sf    5 年前

    允许 ncl 是所需的群集数。我们可以生成一个采样空间 S 这是一个公差序列 tol 每个星团的平均观测值 mnobs .从中我们得出 repeat etly随机抽取大小为1的样本,以获得集群列表 CL .如果集群的总和 lengths 遇见 ncl*mnobs 我们 break 循环,向集群添加随机数据,然后 rbind 结果呢。

    FUN <- function(ncl=20, mnobs=30, tol=.1) {
      S <- do.call(seq.int, as.list(mnobs*(1 + tol*c(-1, 1))))
      repeat({
        CL <- lapply(1:ncl, function(x) rep(x, sample(S, 1, replace=T)))
        if (sum(lengths(CL)) == ncl*mnobs) break
      })
      L <- lapply(seq.int(CL), function(i) {
        id <- seq.int(CL[[i]])
        cbind(id, cluster=i, 
              matrix(rnorm(max(id)*2),,2, dimnames=list(NULL, c("x", "y"))))
      })
      do.call(rbind.data.frame, L)
    }
    

    用法

    set.seed(42)
    res <- FUN()  ## using defined `arg` defaults
    dim(res)
    # [1] 600   4
    
    (res.tab <- table(res$cluster))
    #  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 
    # 29 29 31 31 30 32 31 30 32 28 28 27 28 31 32 33 31 30 27 30
    
    table(res.tab)
    # 27 28 29 30 31 32 33 
    #  2  3  2  4  5  3  1
    
    sapply(c("mean", "sd"), function(x) do.call(x, list(res.tab)))
    #      mean        sd 
    # 30.000000  1.747178 
    

    可显示示例

    set.seed(42)
    FUN(4, 5, tol=.3)  ## tol needs to be adjusted for smaller samples
    #    id cluster           x          y
    # 1   1       1  1.51152200 -0.0627141
    # 2   2       1 -0.09465904  1.3048697
    # 3   3       1  2.01842371  2.2866454
    # 4   1       2 -1.38886070 -2.4404669
    # 5   2       2 -0.27878877  1.3201133
    # 6   3       2 -0.13332134 -0.3066386
    # 7   4       2  0.63595040 -1.7813084
    # 8   5       2 -0.28425292 -0.1719174
    # 9   6       2 -2.65645542  1.2146747
    # 10  1       3  1.89519346 -0.6399949
    # 11  2       3 -0.43046913  0.4554501
    # 12  3       3 -0.25726938  0.7048373
    # 13  4       3 -1.76316309  1.0351035
    # 14  5       3  0.46009735 -0.6089264
    # 15  1       4  0.50495512  0.2059986
    # 16  2       4 -1.71700868 -0.3610573
    # 17  3       4 -0.78445901  0.7581632
    # 18  4       4 -0.85090759 -0.7267048
    # 19  5       4 -2.41420765 -1.3682810
    # 20  6       4  0.03612261  0.4328180