R 创建N个无间距的随机整数

R 创建N个无间距的随机整数,r,R,对于我正在实现的集群算法,我希望随机初始化集群分配。然而,我需要的是没有差距。也就是说,这不好: set.seed(2) K <- 10 # initial number of clusters N <- 20 # number of data points z_init <- sample(K,N, replace=TRUE) # initial assignments z_init # [1] 2 8 6 2 10 10 2 9 5 6 6 3 8

对于我正在实现的集群算法,我希望随机初始化集群分配。然而,我需要的是没有差距。也就是说,这不好:

set.seed(2)
K <- 10 # initial number of clusters
N <- 20 # number of data points
z_init <- sample(K,N, replace=TRUE) # initial assignments
z_init
#  [1]  2  8  6  2 10 10  2  9  5  6  6  3  8  2  5  9 10  3  5  1
sort(unique(z_init))
# [1]  1  2  3  5  6  8  9 10
其中,标签5已变为4,以此类推,以填充较低的空标签

更多示例:

  • 向量
    123568
    应该是
    ̀1234567
  • 向量
    15,5,7,7,10
    应为
    ̀1 2 3 4
可以为循环避免
吗?我不需要它太快,我更喜欢它优雅而简短,因为我在代码中只做了一次(用于标签初始化)

我的解决方案使用
for
循环

z_init <- c(3,2,1,3,3,7,9)

idx <- order(z_init)
for (i in 2:length(z_init)){
  if(z_init[idx[i]] > z_init[idx[i-1]]){
    z_init[idx[i]] <- z_init[idx[i-1]]+1
  }
  else{
    z_init[idx[i]] <- z_init[idx[i-1]]  
  }

}

z_init
# 3 2 1 3 3 4 5

z_init在我看来,您试图将集合中的元素(数字1到20)随机分配给簇,但要求每个簇至少分配一个元素

我能想到的一种方法是选择一个随机奖励
r_ij
,将元素
I
分配给集群
j
。然后我将定义二进制决策变量
x_ij
,它指示元素
I
是否分配给集群
j
。最后,我将使用混合整数优化来选择从元素到集群的分配,以在以下条件下最大化收集的奖励:

  • 每个元素只分配给一个簇
  • 每个集群至少分配了一个元素
这相当于随机选择一个分配,如果所有集群至少有一个元素,则保留该分配,否则将丢弃该分配并重试,直到获得有效的随机分配

就实现而言,使用
lpSolve
包在R中很容易实现:

library(lpSolve)
N <- 20
K <- 10
set.seed(144)
r <- matrix(rnorm(N*K), N, K)
mod <- lp(direction = "max",
          objective.in = as.vector(r),
          const.mat = rbind(t(sapply(1:K, function(j) rep((1:K == j) * 1, each=N))),
                            t(sapply(1:N, function(i) rep((1:N == i) * 1, K)))),
          const.dir = c(rep(">=", K), rep("=", N)),
          const.rhs = rep(1, N+K),
          all.bin = TRUE)
(assignments <- apply(matrix(mod$solution, nrow=N), 1, function(x) which(x > 0.999)))
#  [1]  6  5  3  3  5  6  6  9  2  1  3  4  7  6 10  2 10  6  6  8
sort(unique(assignments))
#  [1]  1  2  3  4  5  6  7  8  9 10
库(lpSolve)

N您可以这样做:

un <- sort(unique(z_init))
(z <- unname(setNames(1:length(un), un)[as.character(z_init)]))
# [1] 2 6 5 2 8 8 2 7 4 5 5 3 6 2 4 7 8 3 4 1
sort(unique(z))
# [1] 1 2 3 4 5 6 7 8
un一种简单(但可能效率低下)的方法是将系数转换为数值。创建因子将把信息编码为从1到唯一值的整数,然后用原始值添加标签。转换为数字,然后删除标签并保留数字:

> x <- c(1,2,3,5,6,8)
> (x2 <- as.numeric(factor(x)))
[1] 1 2 3 4 5 6
> 
> xx <- c(15,5,7,7,10)
> (xx2 <- as.numeric(factor(xx)))
[1] 4 1 2 2 3
> (xx3 <- as.numeric(factor(xx, levels=unique(xx))))
[1] 1 2 3 3 4
>x(x2

>xx(xx2)(xx3编辑:@GregSnow给出了当前最短的答案。我100%相信这是最短的可能方式

为了好玩,我决定把代码写得尽可能短:

z <- c(3, 8, 4, 4, 8, 2, 3, 9, 5, 1, 4)
# solution by hand: 1 2 3 3 4 4 4 5 6 6 7

sort(c(factor(z))) # 18 bits, as proposed by @GregSnow in the comments
# [1] 1 2 3 3 4 4 4 5 6 6 7
Edit2:只是为了说明比特并不是一切:

z <- sample(1:10,10000,replace=T)
Unit: microseconds
                                      expr      min        lq      mean    median        uq      max neval
                        sort(c(factor(z))) 2550.128 2572.2340 2681.4950 2646.6460 2729.7425 3140.288   100
   {     y = table(z)     rep(seq(y), y) } 2436.438 2485.3885 2580.9861 2556.4440 2618.4215 3070.812   100
                  sort(unclass(factor(z))) 2535.127 2578.9450 2654.7463 2623.9470 2708.6230 3167.922   100
            diffinv(diff(sort(z)) > 0) + 1  551.871  572.2000  628.6268  626.0845  666.3495  940.311   100
               sort(as.numeric(factor(z))) 2603.814 2672.3050 2762.2030 2717.5050 2790.7320 3558.336   100
             rep(seq(unique(z)), table(z)) 2541.049 2586.0505 2733.5200 2674.0815 2760.7305 5765.815   100
           cumsum(c(1, diff(sort(z)) > 0))  530.159  545.5545  602.1348  592.3325  632.0060  844.385   100
{  y = rle(sort(z))$l     rep(seq(y), y) }  661.218  684.3115  727.4502  724.1820  758.3280  857.412   100

z <- sample(1:100000,replace=T)
Unit: milliseconds
                                      expr       min        lq     mean    median       uq       max neval
                        sort(c(factor(z))) 84.501189 87.227377 92.13182 89.733291 94.16700 150.08327   100
   {     y = table(z)     rep(seq(y), y) } 78.951701 82.102845 85.54975 83.935108 87.70365 106.05766   100
                  sort(unclass(factor(z))) 84.958711 87.273366 90.84612 89.317415 91.85155 121.99082   100
            diffinv(diff(sort(z)) > 0) + 1  9.784041  9.963853 10.37807 10.090965 10.34381  17.26034   100
               sort(as.numeric(factor(z))) 85.917969 88.660145 93.42664 91.542263 95.53720 118.44512   100
             rep(seq(unique(z)), table(z)) 86.568528 88.300325 93.01369 90.577281 94.74137 118.03852   100
           cumsum(c(1, diff(sort(z)) > 0))  9.680615  9.834175 10.11518  9.963261 10.16735  14.40427   100
 { y = rle(sort(z))$l     rep(seq(y), y) } 12.842614 13.033085 14.73063 13.294019 13.66371 133.16243   100
z0)+1551.871 572.2000 628.6268 626.0845 666.3495 940.311100
排序(如数字(系数(z)))2603.8142672.30502762.2030 2717.50502790.7320 3558.336100
代表(唯一(z)),表(z))2541.049 2586.0505 2733.5200 2674.0815 2760.7305 5765.815 100
积数(c(1,diff(sort(z))>0))530.159 545.5545 602.1348 592.3325 632.0060 844.385 100
{y=rle(sort(z))$l rep(seq(y),y)}661.218684.3115727.4502724.1820758.3280857.412100
z 0)+19.784041 9.963853 10.37807 10.090965 10.34381 17.26034 100
排序(如数字(因子(z)))85.917969 88.660145 93.42664 91.542263 95.53720 118.44512 100
表(z))86.568528 88.300325 93.01369 90.577281 94.74137 118.03852 100
积数(c(1,diff(sort(z))>0))9.680615 9.834175 10.11518 9.963261 10.16735 14.40427 100
{y=rle(sort(z))$l rep(seq(y),y)}12.842613.033085 14.73063 13.294019 13.66371 133.16243 100

很抱歉,我不理解所需输出的逻辑。您能更准确地说明您想要实现的目标吗?您可能需要对数据进行后处理。确定元素的最大数量,对其进行排序并替换。我突然想到了汽车包中的重新编码功能。您为什么要随机初始化集群标签而不是随机的星团质心?这对我们来说没有意义me@Alex这是一个高斯混合模型,其中我(吉布斯)采样z|u 1~p(z|u 1 | z|u 2,z|u 3),z|u 2~p(z|u 2 | z|u 3,z|u 2)等等,所以我需要将所有点分配给某个集群。问题是,我正在调试阶段,我想确保算法始终运行良好。@alberto在聊天/电子邮件中可能会更好,但想分享你的代码吗?我有一个包,它通过EM(不是通过Gibbs,尽管这很容易添加)实现高斯混合模型。我的测试不需要任意分配标签。
unclass
功能可以用
c
替换,
c
有时有益,有时有害的副作用是它删除属性,在这里起到了
unclass
的作用。我不知道这是否会影响计时。它将是集成的休息一下,看看一些大向量的时间安排。一些算法可能比其他算法扩展得更好……哇。我确信我已经尝试过了。显然没有:)更新到你的答案,并将微基准更新到10000和100000个主菜。
y=table(z);rep(seq(y),y) # 24 bits
sort(unclass(factor(z))) # 24 bits, based on @GregSnow 's answer
diffinv(diff(sort(z))>0)+1 # 26 bits
sort(as.numeric(factor(z))) # 27 bits, @GregSnow 's original answer
rep(seq(unique(z)),table(z)) # 28 bits
cumsum(c(1,diff(sort(z))>0)) # 28 bits
y=rle(sort(z))$l;rep(seq(y),y) # 30 bits
z <- sample(1:10,10000,replace=T)
Unit: microseconds
                                      expr      min        lq      mean    median        uq      max neval
                        sort(c(factor(z))) 2550.128 2572.2340 2681.4950 2646.6460 2729.7425 3140.288   100
   {     y = table(z)     rep(seq(y), y) } 2436.438 2485.3885 2580.9861 2556.4440 2618.4215 3070.812   100
                  sort(unclass(factor(z))) 2535.127 2578.9450 2654.7463 2623.9470 2708.6230 3167.922   100
            diffinv(diff(sort(z)) > 0) + 1  551.871  572.2000  628.6268  626.0845  666.3495  940.311   100
               sort(as.numeric(factor(z))) 2603.814 2672.3050 2762.2030 2717.5050 2790.7320 3558.336   100
             rep(seq(unique(z)), table(z)) 2541.049 2586.0505 2733.5200 2674.0815 2760.7305 5765.815   100
           cumsum(c(1, diff(sort(z)) > 0))  530.159  545.5545  602.1348  592.3325  632.0060  844.385   100
{  y = rle(sort(z))$l     rep(seq(y), y) }  661.218  684.3115  727.4502  724.1820  758.3280  857.412   100

z <- sample(1:100000,replace=T)
Unit: milliseconds
                                      expr       min        lq     mean    median       uq       max neval
                        sort(c(factor(z))) 84.501189 87.227377 92.13182 89.733291 94.16700 150.08327   100
   {     y = table(z)     rep(seq(y), y) } 78.951701 82.102845 85.54975 83.935108 87.70365 106.05766   100
                  sort(unclass(factor(z))) 84.958711 87.273366 90.84612 89.317415 91.85155 121.99082   100
            diffinv(diff(sort(z)) > 0) + 1  9.784041  9.963853 10.37807 10.090965 10.34381  17.26034   100
               sort(as.numeric(factor(z))) 85.917969 88.660145 93.42664 91.542263 95.53720 118.44512   100
             rep(seq(unique(z)), table(z)) 86.568528 88.300325 93.01369 90.577281 94.74137 118.03852   100
           cumsum(c(1, diff(sort(z)) > 0))  9.680615  9.834175 10.11518  9.963261 10.16735  14.40427   100
 { y = rle(sort(z))$l     rep(seq(y), y) } 12.842614 13.033085 14.73063 13.294019 13.66371 133.16243   100