R:如何生成每个rowSum为1的数据帧

时间:2016-03-09 01:17:36

标签: r combinations

我有一个包含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的新手。

感谢您的帮助。

2 个答案:

答案 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

真的有点虎头蛇尾。