如何计算 R 中列表的笛卡尔幂
How to calculate the Cartesian Power of a list in R
我想生成 R 中任意集合的笛卡尔幂。
例如在 Python 中,我将按以下方式进行:
from itertools import product
c = [1, 2, 3]
n = 2
l = list(product(c, repeat=n))
这会导致以下输出。
[(1, 1)
(1, 2)
(1, 3)
(2, 1)
(2, 2)
(2, 3)
(3, 1)
(3, 2)
(3, 3)]
我对 R 很陌生,所以我想知道是否有一个内置函数可以用来实现这一点。请注意,我对增加功率特别感兴趣(Python 中的重复参数)。
感谢@G.Grothendieck解答问题!
s <- c(1, 2, 3)
n <- 2
do.call("expand.grid", rep(list(s), n))
这是给出正确结果的 R 代码。
建议的解决方案忽略顺序。您会注意到 expand.grid
在每次迭代时迭代 最左边的元素 ,这不会产生与 python 相同的顺序的 itertools.product
生成器。观察:
s <- c(1, 2, 3)
n <- 2
do.call("expand.grid", rep(list(s), n))
Var1 Var2
1 1 1
2 2 1
3 3 1
4 1 2 <-- This is the second result using python's product
5 2 2
6 3 2
7 1 3 <-- This is the third result using python's product
8 2 3
9 3 3
与python解决方案的输出相比:
from itertools import product
c = [1, 2, 3]
n = 2
list(product(c, repeat=n))
[(1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 2),
(2, 3),
(3, 1),
(3, 2),
(3, 3)]
来自 itertools.product() 文档(强调我的):
The nested loops cycle like an odometer with the rightmost element advancing on every iteration. This pattern creates a lexicographic ordering so that if the input’s iterables are sorted, the product tuples are emitted in sorted order.
将此与此答案顶部(即最左边)的内容进行比较。
幸运的是,在 R
(或与此相关的任何语言)中生成完全相同的输出相对容易,因为这些只是简单的重复排列。如果您想构建自己的生成器,如 python
,算法相对简单,如文档所建议的那样(即 "Roughly equivalent to nested for-loops in a generator expression")。
有一些包能够以所需的顺序相当有效地生成这些包。它们是 gtools
、arrangements
和 RcppAlgos
*.
这是所有三个的代码:
gtools::permutations(3, 2, repeats.allowed = T)
arrangements::permutations(3, 2, replace = T)
RcppAlgos::permuteGeneral(3, 2, T)
好处是,这些解决方案比使用 expand.grid
:
更有效
system.time(do.call("expand.grid", rep(list(1:7), 8)))
user system elapsed
0.375 0.007 0.382
system.time(RcppAlgos::permuteGeneral(7, 8, T))
user system elapsed
0.057 0.032 0.088
RcppAlgos::permuteCount(7, 8, T)
[1] 5764801
事实上,它们甚至比 python
解决方案更快:
import time
def getTime():
start = time.time()
list(product([1, 2, 3, 4, 5, 6, 7], repeat = 8))
end = time.time()
print(end - start)
getTime()
0.9604620933532715
公平地说,itertools
意味着 迭代 因此内存效率高,并不是真正意味着一次生成所有结果。
* 我是 RcppAlgos
的作者
我想生成 R 中任意集合的笛卡尔幂。 例如在 Python 中,我将按以下方式进行:
from itertools import product
c = [1, 2, 3]
n = 2
l = list(product(c, repeat=n))
这会导致以下输出。
[(1, 1)
(1, 2)
(1, 3)
(2, 1)
(2, 2)
(2, 3)
(3, 1)
(3, 2)
(3, 3)]
我对 R 很陌生,所以我想知道是否有一个内置函数可以用来实现这一点。请注意,我对增加功率特别感兴趣(Python 中的重复参数)。
感谢@G.Grothendieck解答问题!
s <- c(1, 2, 3)
n <- 2
do.call("expand.grid", rep(list(s), n))
这是给出正确结果的 R 代码。
建议的解决方案忽略顺序。您会注意到 expand.grid
在每次迭代时迭代 最左边的元素 ,这不会产生与 python 相同的顺序的 itertools.product
生成器。观察:
s <- c(1, 2, 3)
n <- 2
do.call("expand.grid", rep(list(s), n))
Var1 Var2
1 1 1
2 2 1
3 3 1
4 1 2 <-- This is the second result using python's product
5 2 2
6 3 2
7 1 3 <-- This is the third result using python's product
8 2 3
9 3 3
与python解决方案的输出相比:
from itertools import product
c = [1, 2, 3]
n = 2
list(product(c, repeat=n))
[(1, 1),
(1, 2),
(1, 3),
(2, 1),
(2, 2),
(2, 3),
(3, 1),
(3, 2),
(3, 3)]
来自 itertools.product() 文档(强调我的):
The nested loops cycle like an odometer with the rightmost element advancing on every iteration. This pattern creates a lexicographic ordering so that if the input’s iterables are sorted, the product tuples are emitted in sorted order.
将此与此答案顶部(即最左边)的内容进行比较。
幸运的是,在 R
(或与此相关的任何语言)中生成完全相同的输出相对容易,因为这些只是简单的重复排列。如果您想构建自己的生成器,如 python
,算法相对简单,如文档所建议的那样(即 "Roughly equivalent to nested for-loops in a generator expression")。
有一些包能够以所需的顺序相当有效地生成这些包。它们是 gtools
、arrangements
和 RcppAlgos
*.
这是所有三个的代码:
gtools::permutations(3, 2, repeats.allowed = T)
arrangements::permutations(3, 2, replace = T)
RcppAlgos::permuteGeneral(3, 2, T)
好处是,这些解决方案比使用 expand.grid
:
system.time(do.call("expand.grid", rep(list(1:7), 8)))
user system elapsed
0.375 0.007 0.382
system.time(RcppAlgos::permuteGeneral(7, 8, T))
user system elapsed
0.057 0.032 0.088
RcppAlgos::permuteCount(7, 8, T)
[1] 5764801
事实上,它们甚至比 python
解决方案更快:
import time
def getTime():
start = time.time()
list(product([1, 2, 3, 4, 5, 6, 7], repeat = 8))
end = time.time()
print(end - start)
getTime()
0.9604620933532715
公平地说,itertools
意味着 迭代 因此内存效率高,并不是真正意味着一次生成所有结果。
* 我是 RcppAlgos