MEMORY1 MEMORY2 MEMORY3 MEMORY4 MEMORY5 MEMORY6 MEMORY7 MEMORY8
1 2.5 2.5 4 5 6 7 8
假设我有以上8个项目的排名。有两种方法可以打破这种关系:1 2 3 4 5 6 7 8
或1 3 2 4 5 6 7 8
。我正在尝试编写一个函数,当给出原始排名时,它会输出这两个可能的序列。
在
的情况下 MEMORY1 MEMORY2 MEMORY3 MEMORY4 MEMORY5 MEMORY6 MEMORY7 MEMORY8
4.5 4.5 4.5 4.5 4.5 4.5 4.5 4.5
所有项目都是绑定的,因此有8!
个可能的序列。 permn(8)
或类似的东西可以很好地枚举序列。
在
的情况下 MEMORY1 MEMORY2 MEMORY3 MEMORY4 MEMORY5 MEMORY6 MEMORY7 MEMORY8
7.5 5 5 2 7.5 2 2 5
有3! x 3! x 2! = 72
个可能的序列。如何根据原始排名编写输出这72个可能序列的函数?
myfun = function(ranking){
output = vector()
values = sort(unique(ranking))
if(length(values) < 8){
#if there are ties
for(i in 1:length(values)){
value_in_question = values[i]
if(sum(value_in_question %in% values[i] == 1)){
output = output
}else output[i] = permn(values[i])
}
}
return(output)
}
这是我的尝试,它不起作用。当有多个关系时,我无法想出一种枚举序列的方法......
修改
dat = c(2.5, 2.5, 2.5, 2.5, 6.5, 6.5, 6.5, 6.5)
names(dat) <- paste0("MEMORY", 1:8)
## Group similar items, compute run lengths, then permute
library(combinat) # permn
gs <- cumsum(abs(c(0, diff(sort(dat)))) > 1e-9)
lens <- rle(gs)$lengths
lst <- mapply(function(a,b) lapply(permn(1:b), `+`, a), c(0, cumsum(head(lens, -1))), lens)
## Expand into data.frame (don't expand if all were the same)
res <- if(!is.null(dim(lst)) && dim(lst)[2] == 1) lst else expand.grid(lst)
Error: cannot allocate vector of size 16.0 Gb
In addition: Warning messages:
1: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
2: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
3: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
4: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
5: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
6: In rep.int(seq_len(nx), rep.int(rep.fac, nx)) :
Reached total allocation of 8070Mb: see help(memory.size)
答案 0 :(得分:1)
由于您要比较浮点数,因此您不想使用==
测试。相反,检查数字之间的差异是否足够小。这是一个可能的解决方案,没有对效率提出任何要求。
## Example
dat <- c(7.5, 5, 5, 2, 7.5, 2, 2, 5)
names(dat) <- paste0("MEMORY", 1:8)
## Group similar items, compute run lengths, then permute
library(combinat) # permn
gs <- cumsum(abs(c(0, diff(sort(dat)))) > 1e-9)
lens <- rle(gs)$lengths
lst <- mapply(function(a,b) lapply(permn(1:b), `+`, a),
c(0, cumsum(head(lens, -1))), lens, SIMPLIFY = FALSE)
## Expand into data.frame (don't expand if all were the same)
res <- if(!is.null(dim(lst)) && dim(lst)[2] == 1) lst else expand.grid(lst)
## Unnest columns if desired
res <- data.frame(t(apply(res, 1, unlist)))
## Name the columns
names(res) <- names(sort(dat))
head(res)
# MEMORY4 MEMORY6 MEMORY7 MEMORY2 MEMORY3 MEMORY8 MEMORY1 MEMORY5
# 1 1 2 3 4 5 6 7 8
# 2 1 3 2 4 5 6 7 8
# 3 3 1 2 4 5 6 7 8
# 4 3 2 1 4 5 6 7 8
# 5 2 3 1 4 5 6 7 8
# 6 2 1 3 4 5 6 7 8
## Gets all 72 sequences from example: 3!*3!*2!
nrow(res)
# [1] 72
结果应该是data.frame,其中每一行是可能的序列之一(序列是排序数据的索引)。