我有一个包含15列和11行的数据帧。行值从0.0增加到1.0,增量为0.1。我想要做的是生成所有组合,但只保留每行总和为1的组合。我尝试使用expand.grid,但有15列,显然我的内存不足。
以下代码适用于5列,但我需要对15或20列执行相同的操作。
df <- data.frame(matrix(rep(seq(0.0,1.0,by=0.1),5), 11, 5))
df.grid <- expand.grid(df)
df.grid[which(rowSums(df.grid)==1),]
我确信有一种简单的方法可以做到这一点,但我是R的新手。
感谢您的帮助。
答案 0 :(得分:0)
我想我可能已从右边的一个建议帖子中找到答案。我还在检查。但这是答案。
=== myapp Heroku Domain
myapp.herokuapp.com
=== myapp Custom Domains
Domain Name DNS Target
------------------ -------------------
www.myapp.com myapp.herokuapp.com
myapp.com myapp.herokuapp.com
答案 1 :(得分:0)
您需要尽量减少计算机需要完成的工作,因为您在这里处理了很多组合。首先,将您正在操作的数字集限制为最小集。鉴于1
已经总和为1,您的集合中不需要多个1
。另一方面,您不希望超过十0.1
秒。然后,您可以通过将1除以唯一数字序列的结果取底来获得全套:
x <- seq(.1, 1, by = .1) # initialize 0.1:1 sequence
x <- rep(x, floor(1/x)) # repeat minimal set for all combinations
只有27个数字:
> x
[1] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.2 0.2 0.2 0.2 0.2 0.3 0.3 0.3 0.4 0.4 0.5 0.5 0.6
[24] 0.7 0.8 0.9 1.0
现在你需要循环combn
超过组合中可能数量的术语,这些术语将从1运行到1/min(x)
,即10.然后我们可以索引到{{1 } {(colSums == 1
将组合作为列返回):
combn
考虑到尺寸(在我的笔记本电脑上37秒生成1Mb的10个矩阵列表),这可以在不合理的时间内工作,但它仍然会返回重复组合的批次,因为每次迭代包含更多副本一些不必要的数字;例如当选择3时,没有任何一秒lapply(seq_len(1/min(x)), function(y){z <- combn(x, y); z[,colSums(z) == 1]})
,或0.5
将被返回两次。
它也不是一种非常方便的格式,因为所有矩阵都有不同的尺寸。如果我们向0.2 0.3 0.5
添加一个函数来添加combn
s,那么每个组合的长度都为10,NA
需要2-3倍的长度,但它确实允许我们轻松组合他们使用lapply
,因此可以轻松使用do.call(rbind, ... )
将其缩减为唯一组合。
unique.matrix
或者,您可以使用x <- seq(.1, 1, by = .1) # initialize 0.1:1 sequence
x <- rep(x, floor(1/x)) # repeat minimal set for all combinations
results <- lapply(seq_len(max(x)/min(x)), function(y){
# calculate combinations; fill lengths to 10 with NA to allow easy joining later
z <- combn(x, y, function(x){c(x, rep(NA, 10 - y))})
z[,colSums(z, na.rm = TRUE) == 1]}) # chop to combinations with sum == 1
results <- do.call(cbind, results) # combine 10 matrices
results <- unique.matrix(results, MARGIN = 2) # remove remaining repeats
执行第二次lapply
并在之后插入unique.matrix
,这可能会更快,但上面的版本是一个很好的桥接案例但是。
如果我们优化可能有用的数字列表以在我们的循环中组合,我们可以计算许多,更少的组合,从而显着加快过程,直到它几乎瞬间执行。仍然会有一些重复,因为某些数字需要重复某些数字而不是其他数字,但我们可以使用上述方法来简化:
NA
请注意,results <- lapply(seq_len(10), function(y){
x <- seq(.1, 1, by = .1) # initialize 0.1:1 sequence
# calculate minimum repititions of each number; .099 to avoid floating point error
reps <- ifelse(y <= floor((1 - .1 * (y - 1)) / (x - .099)),
ifelse(y * x == 1, y, y - 1),
floor((1 - .1 * (y - 1)) / (x - .099)) )
x <- rep(x, reps) # build set with necessary repeats
# calculate combinations; fill lengths to 10 with NA to allow easy joining later
z <- combn(x, y, FUN = function(x){c(x, rep(NA, 10 - y))})
z[, colSums(z, na.rm = TRUE) == 1] # chop to combinations with sum == 1
})
results <- do.call(cbind, results) # combine 10 matrices
results <- unique.matrix(results, MARGIN = 2) # remove remaining repeats
表达式在数学上可能不是理想的,但在此处为所有10次迭代生成正确的集合。 (如果你有更好的版本,请发表评论!)
总而言之,你得到了41个组合的矩阵,你可能已经手工写出了。
reps
真的有点虎头蛇尾。