根据所有可能的组合重新组织数据集

时间:2015-11-17 18:27:08

标签: r

假设我有三个人ABC的数据,并且每个人都有两个特征,"学年和#34;({ {1}})和"兄弟姐妹的数量"(YS)。因此,数据集NS如下所示:

X

现在,我必须根据id <- c("A", "B", "C") YS <- c(6, 9, 8) NS <-c(1, 0, 3) X <- data.frame(id, YS, NS) AB的所有可能组合重新整理数据集,这意味着将有2 ^ 3-1组合。更准确地说,这些组合包括:CABCABACBCABC组合(即2 ^ 3-1组合)。除了组合个体之外,我还必须计算每个组合的每个特征的值。例如,组合null的{​​{1}}和YS值为15和1.另一个例子,NSAB的值为组合YS分别为23和4。

我理解使用代码NS生成可能的组合,但我不知道如何同时组合特征值。有人可以帮忙吗?感谢。

4 个答案:

答案 0 :(得分:3)

不是很漂亮或像R一样,但它有效。它包括根据问题设置的NULL。

# function to create the combinations and sum the elements
reorgCombs <- function(data) {
    ids <- rownames(data)
    newdata <- 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 <- t(combn(ids, i))
        newdata <- 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 <- cbind(YS, NS)
rownames(X2) <- 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

使用新基准编辑:

也许是因为查询表,即使循环它的相对较快 - 但以马修的解决方案为主

## 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

答案 1 :(得分:3)

这是combn

的另一个选项
all_combn <- function(x, ...)
    unlist(sapply(seq_along(x), combn, x=x, ...))

data.frame(
   id=all_combn(id, paste, collapse=''),
   YS=all_combn(YS, sum),
   NS=all_combn(NS, sum)
)

#    id YS NS
# 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

答案 2 :(得分:1)

这是在基地R中进行此操作的一种方法。首先,确定组合:

n = nrow(X)
combos = do.call(rbind, lapply(seq(n), function(x){
  r = combn(n, x)
  data.frame( r = c(r), g = paste(x, c(col(r)), sep=".") )
}))

然后,为每个组合选择X行:

Xc    = X[combos$r,]
Xc$id = as.character(Xc$id)
Xc$g  = ave(Xc$id, combos$g, FUN = function(x) paste0(x,collapse=''))

最后,每个组合的聚合:

aggregate(cbind(YS,NS)~g, Xc, sum)

#     g YS NS
# 1   A  6  1
# 2  AB 15  1
# 3 ABC 23  4
# 4  AC 14  4
# 5   B  9  0
# 6  BC 17  3
# 7   C  8  3

您以这种方式错过了空集,但如果需要,rbind就足够了。

答案 3 :(得分:0)

看起来很多,但我碰巧使用splitstackshape作为另一个答案,并在这里看到了应用程序的可能性。第一个电话是lst1 <- do.call(c, "all combinations")。这就像你提到的所有可能性一样创建了列表。如果您愿意,可以稍后添加NULL之类的边缘案例。我们从lst1创建一个数据框来组织信息。函数cSplitdf重新整形为长整数。我们合并以添加数字值。最后,使用dplyr我们按照我们创建的索引列进行分组,将所有因素转换为integer类型,然后找到总和:

library(dplyr)
library(splitstackshape)

lst1 <- do.call(c, lapply(1:3, function(i) combn(id, i, simplify=F)))
df <- data.frame(indx=seq_along(lst1), combs=sapply(lst1, toString))
df.long <- cSplit(df, 'combs', direction="long")

m <- merge(X, df.long, by.x='id', by.y='combs')
m %>% group_by(indx) %>%
  mutate_each(funs(as.integer(as.character(.))), -id) %>%
  summarise(id=toString(id), YS=sum(YS), NS=sum(NS))
# Source: local data frame [7 x 4]
# 
#    indx      id    YS    NS
#   (int)   (chr) (int) (int)
# 1     1       A     6     1
# 2     2       B     9     0
# 3     3       C     8     3
# 4     4    A, B    15     1
# 5     5    A, C    14     4
# 6     6    B, C    17     3
# 7     7 A, B, C    23     4