 <p>Not very pretty or R-like, but it works. And it includes the NULL set as per the question.</p> <pre><code># function to create the combinations and sum the elements reorgCombs &lt;- function(data) { ids &lt;- rownames(data) newdata &lt;- data.frame(comb = c("NULL", id), YS = c(0, data[, "YS"]), NS = c(0, data[, "NS"]), row.names = NULL) for (i in 2:nrow(data)) { theseCombs &lt;- t(combn(ids, i)) newdata &lt;- rbind(newdata, data.frame(comb = apply(theseCombs, 1, paste0, collapse=""), YS = apply(theseCombs, 1, function(x) sum(data[x, "YS"])), NS = apply(theseCombs, 1, function(x) sum(data[x, "NS"])))) } newdata } # make this a numeric matrix with named dimensions # the names will be used for lookup X2 &lt;- cbind(YS, NS) rownames(X2) &lt;- id reorgCombs(X) ## comb YS NS ## 1 NULL 0 0 ## 1 A 6 1 ## 2 B 9 0 ## 3 C 8 3 ## 4 AB 15 1 ## 5 AC 14 4 ## 6 BC 17 3 ## 7 ABC 23 4 </code></pre> <p><strong>Edited with new benchmarks:</strong></p> <p>Perhaps because of the lookup table, even despite the looping it's <em>relatively fast</em> -- but <strong>whooped by Matthew's solution</strong>:</p> <pre><code>## Unit: relative ## expr min lq mean median uq max neval ## jota 4.479829 4.408874 4.304705 4.455843 4.335172 3.730202 100 ## pierre 11.606636 11.623717 12.743089 12.078027 11.761123 19.271072 100 ## ken 3.034247 3.015091 2.978181 3.040916 2.914744 2.755357 100 ## matthew 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000 100 ## frank 4.572867 4.615341 4.590244 4.719418 4.516317 3.978101 100 </code></pre>