从向量中采样元素对,但不重复

时间:2018-11-06 18:52:06

标签: r

说我有一个像这样的偶数长度的向量:

v <- c(1,1,1,1,2,2,2,3,3,3,4,5,6,7)

它是14个元素长。我希望随机抽样7对元素而不进行替换,但是一条规则是,任何对都不应包含两个相同的元素。

因此以下结果是可以接受的:

1-2, 1-2, 1-2, 1-3, 3-4, 3-5, 6-7

我不确定如何系统地执行此操作。显然,蛮力会起作用,例如

set.seed(1)
v=c(1,1,1,1,2,2,2,3,3,3,4,5,6,7)
length(v)
v1<-sample(v)
pairs <- split(v1, ceiling(seq_along(v1)/2))
sapply(pairs, diff)

 1  2  3  4  5  6  7 
 1  1  2  3 -6 -3  3 

这表明没有对具有重复的元素,因为差异总是不为0。在我的情况下,我需要重复执行1000次,而避免重复并不容易。有没有更有效的方法?

2 个答案:

答案 0 :(得分:3)

dat_list %>% 
    bind_rows %>%
    split(.$id) %>%
    map(~ .x  %>% 
             gather(key, val, Number:node_age) %>%
             group_by(key) %>%
             mutate(rn = row_number())  %>%
             ungroup %>% 
             arrange(rn) %>%
             unite(keyage, key, age) %>%
             mutate(keyage = factor(keyage, levels = unique(keyage))) %>% 
             select(-rn) %>%
             spread(keyage, val))
#$T1
# A tibble: 3 x 8
#  id    Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
#  <fct>  <dbl>    <dbl>      <dbl>    <dbl>      <dbl>    <dbl>      <dbl>
#1 T1       1.1        1          0        1          1        1          2
#2 T1       2.2       NA         NA        2          0        2          1
#3 T1       3.3       NA         NA       NA         NA        3          0

#$T2
# A tibble: 3 x 8
#  id    Height Number_2 node_age_2 Number_3 node_age_3 Number_4 node_age_4
#  <fct>  <dbl>    <dbl>      <dbl>    <dbl>      <dbl>    <dbl>      <dbl>
#1 T2       1.2        1          0        1          1        1          2
#2 T2       2.3       NA         NA        2          0        2          1
#3 T2       3.4       NA         NA       NA         NA        3          0

我使用 inputProps={ {className: 'pl2 br3 shadow-1 dropdownButtonDate', onKeyDown: this.onKeyPress} } v0 <- table(v) set.seed(2) out <- replicate(7, sample(names(v0), size=2, prob=v0)) out # [,1] [,2] [,3] [,4] [,5] [,6] [,7] # [1,] "1" "2" "4" "1" "3" "2" "6" # [2,] "5" "1" "7" "7" "2" "1" "1" ,以便保证名称和概率相同。 (我不想假设您的实际数据具有相同的结构。)如果您需要整数,那么对我们table(v)来说就很容易。

如果您确实需要names(v0),那么

as.integer

我相信这不会产生任何重复(因为1-2是唯一的,并且默认为apply(out, 2, paste, collapse="-") # [1] "1-5" "2-1" "4-7" "1-7" "3-2" "2-1" "6-1" ),但这是一个经验检验:

names(v0)

答案 1 :(得分:0)

这是您的“蛮力”方法的一种变体(更好地称为“命中或失败”):

rand.pairs <- function(v, time.out = 1000){
  n <- length(v)
  for(i in 1:time.out){
    v <- sample(v)
    first <- v[1:(n/2)]
    second <- v[(n/2+1):n]
    if(all(first != second)) return(unname(rbind(first,second)))
  }
  NULL
}

time.out的意义在于避免无限循环。对于某些输入向量,解决方案可能是不可能的,或者太难碰到。

示例运行:

> v <- c(1,1,1,1,2,2,2,3,3,3,4,5,6,7)
> set.seed(1234)
> rand.pairs(v)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    6    3    3    7    2    2    5
[2,]    1    4    1    1    3    1    2

它足够快,可以运行数千次:

> library(microbenchmark)
> microbenchmark(rand.pairs(v))
Unit: microseconds
          expr min    lq     mean median     uq    max neval
 rand.pairs(v) 6.7 7.758 16.17517 12.166 19.747 70.877   100

您的行驶里程可能会有所不同,但是如果您的机器完全可以与之媲美,则您应该能够每秒调用50,000次以上。 replicate(10000,rand.pairs(v))的运行时间不到一秒钟。另一方面,如果输入的约束难以满足,则解决方案可能需要更多时间。