6个位置内的3个元素的排列:一个相等的邻居
Permutations of 3 elements within 6 positions: one equal neighbour
考虑到此 post 中的答案,我认为值得就如何对元素进行排序展开新的讨论。
第一个条件是始终具有交替元素的序列:
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a b c a bcabca
# 2 c a b c a b cabcab
# 3 a b c a b c abcabc
# 4 b a b c a b babcab
# 5 c b c a b c cbcabc
# 6 a c a b c a acabca
然而,即使在相似邻居限制中存在一个元素的巧合,其余排列也可能有价值。例如:
# Var1 Var2 Var3 Var4 Var5 Var6 Coincidence
# 1 b b a b c a -->[bb]
# 2 c c b c a b -->[cc]
# 3 a b c a a c -->[aa]
# 4 b a c c a b -->[cc]
是否也可以使用 expand.grid?
如果是"only one more",那么我建议允许最简单的方法就是强制[=37] =]
使用上一题的开头:
r <- replicate(6, seq_len(length(abc)-1), simplify=FALSE)
r[[1]] <- c(r[[1]], length(abc))
我们现在复制这个列表(传递给 expand.grid
)并将第二个到最后一个元素替换为 0。回想一下,我们将这些数字与 cumsum
一起用于更改以前的值,所以用 0
替换 1:2
意味着我们强制下一个元素相同。
rs <- lapply(seq_len(length(r)-1) + 1, function(i) { r[[i]] <- 0; r; })
# ^^^^^^^^^^^^^^^^^^^^^^^^ or: seq_len(length(r))[-1]
str(rs[1:2])
# List of 2
# $ :List of 6
# ..$ : int [1:3] 1 2 3
# ..$ : num 0 <--- the second letter will repeat
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# $ :List of 6
# ..$ : int [1:3] 1 2 3
# ..$ : int [1:2] 1 2
# ..$ : num 0 <--- the third letter will repeat
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
### other rs's are similar
我们可以验证它是否按照我们认为的那样工作:
# rs[[1]] repeats the first 2
m <- t(apply(do.call(expand.grid, rs[[1]]), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
head(as.data.frame(cbind(m, apply(m, 1, paste, collapse = ""))), n=3)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b b c a b c bbcabc
# 2 c c a b c a ccabca
# 3 a a b c a b aabcab
# rs[[3]] repeats the 3rd-4th
m <- t(apply(do.call(expand.grid, rs[[3]]), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
head(as.data.frame(cbind(m, apply(m, 1, paste, collapse = ""))), n=3)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a a b c bcaabc
# 2 c a b b c a cabbca
# 3 a b c c a b abccab
从这里开始,让我们通过将所有这些放入一个列表并 lapply
ing 来自动化它。
rs <- c(list(r), rs)
rets <- do.call(rbind.data.frame, c(stringsAsFactors=FALSE, lapply(rs, function(r) {
m <- t(apply(do.call(expand.grid, r), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
as.data.frame(cbind(m, apply(m, 1, paste, collapse = "")), stringsAsFactors=FALSE)
})))
head(rets)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a b c a bcabca
# 2 c a b c a b cabcab
# 3 a b c a b c abcabc
# 4 b a b c a b babcab
# 5 c b c a b c cbcabc
# 6 a c a b c a acabca
tail(rets)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 331 b c b a c c bcbacc
# 332 c a c b a a cacbaa
# 333 a b a c b b abacbb
# 334 b a c b a a bacbaa
# 335 c b a c b b cbacbb
# 336 a c b a c c acbacc
附加步骤演练:
rs <- c(list(r), rs)
使第一个(非重复 r
)成为一个封闭列表,然后将其添加到 rs
列表中。
lapply(rs, function(r) ...)
对 rs
列表中的每个元素执行上一个问题中的 ...
一次。我在匿名函数中将其命名为 r
以使其非常清楚(在函数内部)每次获得新的 r
时,它都会执行与上一个问题完全相同的步骤。
do.call(rbind.data.frame, c(stringsAsFactors=FALSE, ...
因为 lapply
中的每个 return 将是一个 data.frame,我们希望将它们组合成一个帧。我不喜欢任何因素,但如果需要,您可以选择其他方式。 (而不是 rbind.data.frame
,您可以使用 data.table::rbindlist
或 dplyr::bind_rows
,两者都没有 stringsAsFactors
。)
现在前96行没有重复,然后剩下的五批每批48行(共336行)各有一个重复。我们 "know" 48 是每个重复一次列表的正确数字,因为通过将其中一个位置从“1 2
”更改为“0
”(从 2 到 1可能值)我们将可能组合的总数减半(96 / 2 == 48
)。
如果出于某种原因你的 下一个 问题询问如何扩展它以允许 two 重复......那么我不一定推荐暴力破解 this 方面:有 6 或 10 种可能的重复组合(取决于是否允许 "aaa"
),我更愿意去比单约束的这种蛮力附加更多的编程处理。
考虑到此 post
第一个条件是始终具有交替元素的序列:
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a b c a bcabca
# 2 c a b c a b cabcab
# 3 a b c a b c abcabc
# 4 b a b c a b babcab
# 5 c b c a b c cbcabc
# 6 a c a b c a acabca
然而,即使在相似邻居限制中存在一个元素的巧合,其余排列也可能有价值。例如:
# Var1 Var2 Var3 Var4 Var5 Var6 Coincidence
# 1 b b a b c a -->[bb]
# 2 c c b c a b -->[cc]
# 3 a b c a a c -->[aa]
# 4 b a c c a b -->[cc]
是否也可以使用 expand.grid?
如果是"only one more",那么我建议允许最简单的方法就是强制[=37] =]
使用上一题的开头:
r <- replicate(6, seq_len(length(abc)-1), simplify=FALSE)
r[[1]] <- c(r[[1]], length(abc))
我们现在复制这个列表(传递给 expand.grid
)并将第二个到最后一个元素替换为 0。回想一下,我们将这些数字与 cumsum
一起用于更改以前的值,所以用 0
替换 1:2
意味着我们强制下一个元素相同。
rs <- lapply(seq_len(length(r)-1) + 1, function(i) { r[[i]] <- 0; r; })
# ^^^^^^^^^^^^^^^^^^^^^^^^ or: seq_len(length(r))[-1]
str(rs[1:2])
# List of 2
# $ :List of 6
# ..$ : int [1:3] 1 2 3
# ..$ : num 0 <--- the second letter will repeat
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# $ :List of 6
# ..$ : int [1:3] 1 2 3
# ..$ : int [1:2] 1 2
# ..$ : num 0 <--- the third letter will repeat
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
# ..$ : int [1:2] 1 2
### other rs's are similar
我们可以验证它是否按照我们认为的那样工作:
# rs[[1]] repeats the first 2
m <- t(apply(do.call(expand.grid, rs[[1]]), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
head(as.data.frame(cbind(m, apply(m, 1, paste, collapse = ""))), n=3)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b b c a b c bbcabc
# 2 c c a b c a ccabca
# 3 a a b c a b aabcab
# rs[[3]] repeats the 3rd-4th
m <- t(apply(do.call(expand.grid, rs[[3]]), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
head(as.data.frame(cbind(m, apply(m, 1, paste, collapse = ""))), n=3)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a a b c bcaabc
# 2 c a b b c a cabbca
# 3 a b c c a b abccab
从这里开始,让我们通过将所有这些放入一个列表并 lapply
ing 来自动化它。
rs <- c(list(r), rs)
rets <- do.call(rbind.data.frame, c(stringsAsFactors=FALSE, lapply(rs, function(r) {
m <- t(apply(do.call(expand.grid, r), 1, cumsum) %% length(abc) + 1)
m[] <- abc[m]
as.data.frame(cbind(m, apply(m, 1, paste, collapse = "")), stringsAsFactors=FALSE)
})))
head(rets)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 1 b c a b c a bcabca
# 2 c a b c a b cabcab
# 3 a b c a b c abcabc
# 4 b a b c a b babcab
# 5 c b c a b c cbcabc
# 6 a c a b c a acabca
tail(rets)
# Var1 Var2 Var3 Var4 Var5 Var6 V7
# 331 b c b a c c bcbacc
# 332 c a c b a a cacbaa
# 333 a b a c b b abacbb
# 334 b a c b a a bacbaa
# 335 c b a c b b cbacbb
# 336 a c b a c c acbacc
附加步骤演练:
rs <- c(list(r), rs)
使第一个(非重复r
)成为一个封闭列表,然后将其添加到rs
列表中。lapply(rs, function(r) ...)
对rs
列表中的每个元素执行上一个问题中的...
一次。我在匿名函数中将其命名为r
以使其非常清楚(在函数内部)每次获得新的r
时,它都会执行与上一个问题完全相同的步骤。do.call(rbind.data.frame, c(stringsAsFactors=FALSE, ...
因为lapply
中的每个 return 将是一个 data.frame,我们希望将它们组合成一个帧。我不喜欢任何因素,但如果需要,您可以选择其他方式。 (而不是rbind.data.frame
,您可以使用data.table::rbindlist
或dplyr::bind_rows
,两者都没有stringsAsFactors
。)
现在前96行没有重复,然后剩下的五批每批48行(共336行)各有一个重复。我们 "know" 48 是每个重复一次列表的正确数字,因为通过将其中一个位置从“1 2
”更改为“0
”(从 2 到 1可能值)我们将可能组合的总数减半(96 / 2 == 48
)。
如果出于某种原因你的 下一个 问题询问如何扩展它以允许 two 重复......那么我不一定推荐暴力破解 this 方面:有 6 或 10 种可能的重复组合(取决于是否允许 "aaa"
),我更愿意去比单约束的这种蛮力附加更多的编程处理。