【问题标题】:Sample n by two groups按两组抽样 n
【发布时间】:2017-09-15 13:46:37
【问题描述】:

我有一个如下所示的数据集:

d=data.frame(ID = rep(1:7,1), 
             Group1=c('A','C','B','C','C','A','B'),
             Group2=c('B','A','C','B','B','B','D'))

 ID Group1 Group2
  1      A      B
  2      C      A
  3      B      C
  4      C      B
  5      C      B
  6      A      B
  7      B      D

我需要根据 Group1 随机抽取 1 个案例。 Group1 有三种类型:A、B、C。我需要从每种类型中抽取 1 个样本。

同时,该样本的Group2类型在样本的Group2中不重复。

例如,如果我只基于 Group1 进行采样:

dsample=d %>% group_by(Group1) %>%sample_n(size=1)

那么示例如下所示:

ID Group1 Group2

 1      A      B
 7      B      D
 4      C      B

在样本的Group2中,B在样本中重复出现。为避免Group2类型的重复,在按照Group1类型进行采样时,采样时应选择ID=2,这样样本应如下所示:

ID Group1 Group2

 1      A      B
 7      B      D
 2      C      A

【问题讨论】:

  • 你能描述更多你想要什么吗?...为什么你不使用这个:sample(d$Group1, size=1)
  • 如果数据中没有C A,而只有C B怎么办?你会允许 B 在第 2 组中重复吗?
  • 不,那么应该只随机选择或丢弃 C B 的一种情况,以保持 Group2 中的唯一类型。

标签: r dplyr conditional


【解决方案1】:

一种可能的方法:不断重新采样,直到您获得所需的结果(或直到您失败的次数足够多,以至于您可能无法获得所需的结果):

# data
d=data.frame(ID = rep(1:7,1), 
             Group1=c('A','C','B','C','C','A','B'),
             Group2=c('B','A','C','B','B','B','D'))

# first attempt
dsample = d %>% group_by(Group1) %>% sample_n(size=1)

# if first attempt doesn't work, try again & again (I put an upper limit at 100 runs)
i = 1
while(length(unique(dsample$Group2)) < nrow(dsample) & i < 100){
  dsample = d %>% group_by(Group1) %>% sample_n(size=1)
  i = i + 1
}

> dsample
# A tibble: 3 x 3
# Groups:   Group1 [3]
     ID Group1 Group2
  <int> <fctr> <fctr>
1     1      A      B
2     3      B      C
3     2      C      A

如果所需的唯一组合是不可能的:

# example where "A" & "B" in Group 1 both have only "A" as Group2 values
d2=data.frame(ID = rep(1:7,1), 
             Group1=c('A','C','B','C','C','A','B'),
             Group2=c('A','A','A','C','B','A','A'))

# same code as before
d2sample = d2 %>% group_by(Group1) %>% sample_n(size=1)

i = 1
while(length(unique(d2sample$Group2)) < nrow(d2sample) & i < 100){
  d2sample = d2 %>% group_by(Group1) %>% sample_n(size=1)
  i = i + 1
}

# fail after 100 rounds of resampling
> d2sample
# A tibble: 3 x 3
# Groups:   Group1 [3]
     ID Group1 Group2
  <int> <fctr> <fctr>
1     6      A      A
2     7      B      A
3     5      C      B
> i
[1] 100

【讨论】:

  • 感谢您的解决方案。我在我的数据集上尝试过,所有 Group1 都没有重复类型,但 Group2 仍然有重复类型。我的数据集有 900 多个案例,我很确定样本应该在 300-400 左右。
【解决方案2】:

我的第一个想法是一个 while 循环,然后我意识到我们可以从不同的角度来看看我们是如何采样的。更好的解决方案是一次仅对一行进行采样,然后从仅包含 != Group1 和 != Group2 的先前样本的池中采样下一行。这应该会快很多:

f <- function(){
  x <- sample_n(d,1)
  x <- rbind(x,sample_n(d[which(!d$Group1 %in% x$Group1 & !d$Group2 %in% x$Group2),],1))
  x <- rbind(x,sample_n(d[which(!d$Group1 %in% x$Group1 & !d$Group2 %in% x$Group2),],1))
  print(x)
}

f()

  ID Group1 Group2
6  6      A      B
2  2      C      A
3  3      B      C

如果您知道至少有 2 个唯一的可能样本,则每次随机、非重复输出。

如果有人对如何以这种方式更简洁地重复功能有任何建议,请随时告诉我。不过总的来说,这种方式似乎是最有效的。

【讨论】:

  • @Marble - 这应该是最简单的方法并且适用于大多数情况。如果你想让我为非常小的数据集定制这个,这些数据集不可避免地会有重复项需要删除,请告诉我。
  • 当前函数只返回3个结果。 Group1的类型超过400种怎么办?
【解决方案3】:

试试这个递归函数

您的数据

d=data.frame(ID = rep(1:7,1), 
             Group1=c('A','C','B','C','C','A','B'),
             Group2=c('B','A','C','B','B','B','D'))

dsample=d %>% group_by(Group1) %>%sample_n(size=1)

功能

myfun <- function(ans, allowed, restricted, counter, end) {
             allowed <- setdiff(allowed, ans)
             allowed1 <- setdiff(allowed, restricted[counter])
             if (length(allowed) == 0 | counter > end) {
                  if (length(ans) < end) {
                      ans <- c(ans, rep(NA, end-length(ans)))
                  }
                  return(ans)
             } else {
                  counter <- counter + 1
                  ans <- c(ans, sample(allowed1, 1))
                  myfun(ans, allowed, restricted, counter, end)
             }
         }

10 次试验的输出

replicate(10,myfun(ans=NULL, unique(d$Group2), dsample$Group1, 1, nrow(dsample)))

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] "D"  "C"  "B"  "C"  "B"  "B"  "B"  "B"  "D"  "D"  
[2,] "C"  "D"  "D"  "A"  "D"  "C"  "C"  "A"  "A"  "C"  
[3,] "A"  "B"  "A"  "D"  "A"  "A"  "D"  "D"  "B"  "B"

注意每个复制的输出都是按列组织的

【讨论】:

    猜你喜欢
    • 2013-08-17
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 2020-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    相关资源
    最近更新 更多