R中的序列组合矩阵
Sequence Combination Matrix in R
我想为 5 个变量创建一个矩阵,这样每个变量都从 seq(from = 0, to = 1, length.out = 500)
和 rowSums(data) = 1
中获取一个值。
换句话说,我想知道如何创建一个矩阵来显示所有可能的数字组合以及每个 row = 1
.
的总和
如果我没理解错的话,这至少能让你走上正轨。
# Parameters
len_vec = 500 # vector length
num_col = 5 # number of columns
# Creating the values for the matrix using rational numbers between 0 and 1
values <- runif(len_vec*num_col)
# Creating matrix
mat <- matrix(values,ncol = num_col,byrow = T)
# ROunding the matrix to create only 0s and 1s
mat <- round(mat)
# Calculating the sum per row
apply(mat,1,sum)
这是一个使用循环的迭代解决方案。给你所有可能的数字排列加起来为 1,它们之间的距离是 N 的倍数。这里的想法是将所有数字从 0 到 1(它们之间的距离是 N 的倍数),然后对于每个一个在新列中包含所有添加时不超过 1 的数字。冲洗并重复,除了在最后一次迭代中,在最后一次迭代中,您只添加完成行的数字和行的总和。
就像人们在评论中指出的那样,如果你想要 N = 1/499*,它会给你一个非常非常大的矩阵。我注意到对于 N = 1/200,它已经花费了大约 2、3 分钟,因此对于 N = 1/499 来说可能花费的时间太长了。
*seq(from = 0, to = 1, length.out = 500)
等同于 seq(from = 0, to = 1, by = 1/499)
N = 1/2
M = 5
x1 = seq(0, 1, by = N)
df = data.frame(x1)
for(i in 1:(M-2)){
x_next = sapply(rowSums(df), function(x){seq(0, 1-x, by = N)})
df = data.frame(sapply(df, rep, sapply(x_next,length)))
df = cbind(df, unlist(x_next))
}
x_next = sapply(rowSums(df), function(x){1-x})
df = sapply(df, rep, sapply(x_next,length))
df = data.frame(df)
df = cbind(df, unlist(x_next))
> df
x1 unlist.x_next. unlist.x_next..1 unlist.x_next..2 unlist(x_next)
1 0.0 0.0 0.0 0.0 1.0
2 0.0 0.0 0.0 0.5 0.5
3 0.0 0.0 0.0 1.0 0.0
4 0.0 0.0 0.5 0.0 0.5
5 0.0 0.0 0.5 0.5 0.0
6 0.0 0.0 1.0 0.0 0.0
7 0.0 0.5 0.0 0.0 0.5
8 0.0 0.5 0.0 0.5 0.0
9 0.0 0.5 0.5 0.0 0.0
10 0.0 1.0 0.0 0.0 0.0
11 0.5 0.0 0.0 0.0 0.5
12 0.5 0.0 0.0 0.5 0.0
13 0.5 0.0 0.5 0.0 0.0
14 0.5 0.5 0.0 0.0 0.0
15 1.0 0.0 0.0 0.0 0.0
这正是软件包 partitions
的用途。基本上,OP 正在寻找总和为 499 的 5 个整数的所有可能组合。这可以通过 restrictedparts
:
轻松实现
system.time(combsOne <- t(as.matrix(restrictedparts(499, 5))) / 499)
user system elapsed
1.635 0.867 2.502
head(combsOne)
[,1] [,2] [,3] [,4] [,5]
[1,] 1.000000 0.000000000 0 0 0
[2,] 0.997996 0.002004008 0 0 0
[3,] 0.995992 0.004008016 0 0 0
[4,] 0.993988 0.006012024 0 0 0
[5,] 0.991984 0.008016032 0 0 0
[6,] 0.989980 0.010020040 0 0 0
tail(combsOne)
[,1] [,2] [,3] [,4] [,5]
[22849595,] 0.2024048 0.2004008 0.2004008 0.2004008 0.1963928
[22849596,] 0.2064128 0.1983968 0.1983968 0.1983968 0.1983968
[22849597,] 0.2044088 0.2004008 0.1983968 0.1983968 0.1983968
[22849598,] 0.2024048 0.2024048 0.1983968 0.1983968 0.1983968
[22849599,] 0.2024048 0.2004008 0.2004008 0.1983968 0.1983968
[22849600,] 0.2004008 0.2004008 0.2004008 0.2004008 0.1983968
由于我们处理的是数值,所以我们无法获得精确的精度,但是我们可以获得机器精度:
all(rowSums(combsOne) == 1)
[1] FALSE
all((rowSums(combsOne) - 1) < .Machine$double.eps)
[1] TRUE
有超过 2200 万条结果:
row(combsOne)
[1] 22849600
我想为 5 个变量创建一个矩阵,这样每个变量都从 seq(from = 0, to = 1, length.out = 500)
和 rowSums(data) = 1
中获取一个值。
换句话说,我想知道如何创建一个矩阵来显示所有可能的数字组合以及每个 row = 1
.
如果我没理解错的话,这至少能让你走上正轨。
# Parameters
len_vec = 500 # vector length
num_col = 5 # number of columns
# Creating the values for the matrix using rational numbers between 0 and 1
values <- runif(len_vec*num_col)
# Creating matrix
mat <- matrix(values,ncol = num_col,byrow = T)
# ROunding the matrix to create only 0s and 1s
mat <- round(mat)
# Calculating the sum per row
apply(mat,1,sum)
这是一个使用循环的迭代解决方案。给你所有可能的数字排列加起来为 1,它们之间的距离是 N 的倍数。这里的想法是将所有数字从 0 到 1(它们之间的距离是 N 的倍数),然后对于每个一个在新列中包含所有添加时不超过 1 的数字。冲洗并重复,除了在最后一次迭代中,在最后一次迭代中,您只添加完成行的数字和行的总和。
就像人们在评论中指出的那样,如果你想要 N = 1/499*,它会给你一个非常非常大的矩阵。我注意到对于 N = 1/200,它已经花费了大约 2、3 分钟,因此对于 N = 1/499 来说可能花费的时间太长了。
*seq(from = 0, to = 1, length.out = 500)
等同于 seq(from = 0, to = 1, by = 1/499)
N = 1/2
M = 5
x1 = seq(0, 1, by = N)
df = data.frame(x1)
for(i in 1:(M-2)){
x_next = sapply(rowSums(df), function(x){seq(0, 1-x, by = N)})
df = data.frame(sapply(df, rep, sapply(x_next,length)))
df = cbind(df, unlist(x_next))
}
x_next = sapply(rowSums(df), function(x){1-x})
df = sapply(df, rep, sapply(x_next,length))
df = data.frame(df)
df = cbind(df, unlist(x_next))
> df
x1 unlist.x_next. unlist.x_next..1 unlist.x_next..2 unlist(x_next)
1 0.0 0.0 0.0 0.0 1.0
2 0.0 0.0 0.0 0.5 0.5
3 0.0 0.0 0.0 1.0 0.0
4 0.0 0.0 0.5 0.0 0.5
5 0.0 0.0 0.5 0.5 0.0
6 0.0 0.0 1.0 0.0 0.0
7 0.0 0.5 0.0 0.0 0.5
8 0.0 0.5 0.0 0.5 0.0
9 0.0 0.5 0.5 0.0 0.0
10 0.0 1.0 0.0 0.0 0.0
11 0.5 0.0 0.0 0.0 0.5
12 0.5 0.0 0.0 0.5 0.0
13 0.5 0.0 0.5 0.0 0.0
14 0.5 0.5 0.0 0.0 0.0
15 1.0 0.0 0.0 0.0 0.0
这正是软件包 partitions
的用途。基本上,OP 正在寻找总和为 499 的 5 个整数的所有可能组合。这可以通过 restrictedparts
:
system.time(combsOne <- t(as.matrix(restrictedparts(499, 5))) / 499)
user system elapsed
1.635 0.867 2.502
head(combsOne)
[,1] [,2] [,3] [,4] [,5]
[1,] 1.000000 0.000000000 0 0 0
[2,] 0.997996 0.002004008 0 0 0
[3,] 0.995992 0.004008016 0 0 0
[4,] 0.993988 0.006012024 0 0 0
[5,] 0.991984 0.008016032 0 0 0
[6,] 0.989980 0.010020040 0 0 0
tail(combsOne)
[,1] [,2] [,3] [,4] [,5]
[22849595,] 0.2024048 0.2004008 0.2004008 0.2004008 0.1963928
[22849596,] 0.2064128 0.1983968 0.1983968 0.1983968 0.1983968
[22849597,] 0.2044088 0.2004008 0.1983968 0.1983968 0.1983968
[22849598,] 0.2024048 0.2024048 0.1983968 0.1983968 0.1983968
[22849599,] 0.2024048 0.2004008 0.2004008 0.1983968 0.1983968
[22849600,] 0.2004008 0.2004008 0.2004008 0.2004008 0.1983968
由于我们处理的是数值,所以我们无法获得精确的精度,但是我们可以获得机器精度:
all(rowSums(combsOne) == 1)
[1] FALSE
all((rowSums(combsOne) - 1) < .Machine$double.eps)
[1] TRUE
有超过 2200 万条结果:
row(combsOne)
[1] 22849600