簡體   English   中英

返回所有可能的值組合

[英]Return All Possible Combinations of Values

我有下表:

Group Value
----  ----
1     A
1     B
1     C
1     D
2     A
2     B
2     C

對於這兩組中的每一組,我想返回所有可能的值組合。 對於組1,例如,可能的組合是(A,B),(A,C),(A,D),(B,C),(B,D),(C,D),(A, B,C),(B,D,C),(D,C,A),(C,A,B)。 類比,對於第2組,它是(A,B),(A,C),(B,C)[注:我不想考慮(1)只有一個值的組合,(2)組合所有值和(3)沒有值的組合。 因此,對於n個不同的值,我有2 ^(n)-n-1-1個組合]。

我想在附加欄“Combi”的幫助下列出所有這些組合。 此列連續編號不同的組合。

Group Combi Value
----  ----  ----
1     1     A
1     1     B
1     2     A
1     2     C
1     3     A
1     3     D
1     4     B
1     4     C
1     5     B
1     5     D
1     6     C
1     6     C
1     7     A
1     7     B
1     7     C
1     8     B
1     8     C
1     8     D
1     9     C
1     9     D
1     9     A
1     10    D
1     10    A
1     10    B
2     11    A
2     11    B
2     12    A
2     12    C
2     13    B
2     13    C

我如何在R中執行此操作?

這是一個通用的tidyverse解決方案,應該使用包含3個以上項的值集。

想法是使用combn (m = 2然后3等)並將輸出格式化為不同Groupm值的tibble 從那里我們可以使用tidyverse函數map_dfrunnest 最后,由於我們有多個id而不是一個,我們構建一個唯一ID的表,構建唯一的combi id並將其連接回我們的結果。

# convenience fonction to store combinations in a long format
combi_as_tibble <- function(n,values) combn(values,n) %>%
  {tibble(id = rep(seq(ncol(.)),each=nrow(.)),Value=c(.))}    
combi_as_tibble(2,letters[1:3]) # example
# # A tibble: 6 x 2
#      id Value
#   <chr> <chr>
# 1     1     a
# 2     1     b
# 3     2     a
# 4     2     c
# 5     3     b
# 6     3     c


df1 %>% group_by(Group) %>%
  summarize(combis = list(
    map_dfr(2:(length(unique(Value))-1),combi_as_tibble,Value,.id="id2")
  ))     %>% # by Group, build a long tibble with all combinations
  unnest %>% # unnest to get a long unnested table
  left_join(.,select(.,Group,id2,id) %>% distinct %>% mutate(combi=row_number())
  )      %>% # build combi ids
  select(Group,Value,combi) %>%
  as.data.frame

#    Group Value combi
# 1      1     A     1
# 2      1     B     1
# 3      1     A     2
# 4      1     C     2
# 5      1     A     3
# 6      1     D     3
# 7      1     B     4
# 8      1     C     4
# 9      1     B     5
# 10     1     D     5
# 11     1     C     6
# 12     1     D     6
# 13     1     A     7
# 14     1     B     7
# 15     1     C     7
# 16     1     A     8
# 17     1     B     8
# 18     1     D     8
# 19     1     A     9
# 20     1     C     9
# 21     1     D     9
# 22     1     B    10
# 23     1     C    10
# 24     1     D    10
# 25     2     A    11
# 26     2     B    11
# 27     2     A    12
# 28     2     C    12
# 29     2     B    13
# 30     2     C    13

數據

df1 <- read.table(text="Group Value
1     A
1     B
1     C
1     D
2     A
2     B
2     C",h=T,strin=F)

data.table的可能解決方案:

library(data.table)
setDT(dat)[, .(Value = {n <- 2:(uniqueN(Value)-1);
                        unlist(lapply(n, function(x) combn(Value, x)))})
           , by = Group
           ][, Combi := cumsum(c(1, diff(match(Value, LETTERS)) < 0))][]

這使:

  Group Value Combi 1: 1 A 1 2: 1 B 1 3: 1 A 2 4: 1 C 2 5: 1 A 3 6: 1 D 3 7: 1 B 4 8: 1 C 4 9: 1 B 5 10: 1 D 5 11: 1 C 6 12: 1 D 6 13: 1 A 7 14: 1 B 7 15: 1 C 7 16: 1 A 8 17: 1 B 8 18: 1 D 8 19: 1 A 9 20: 1 C 9 21: 1 D 9 22: 1 B 10 23: 1 C 10 24: 1 D 10 25: 2 A 11 26: 2 B 11 27: 2 A 12 28: 2 C 12 29: 2 B 13 30: 2 C 13 

這是一個基本解決方案。 評論內聯。

#for each length (not incl. 1 and number of unique values), create all possible combinations using combn
combiLs <- by(dat, dat$Group, function(x) {
    #number of elements to choose excl. 1 and all values
    idx <- seq_along(x$Value)[-c(1, nrow(x))]

    do.call(rbind, lapply(idx, function(m) {
        #for each number of elements, generate all combinations
        sets <- combn(x$Value, m, simplify=FALSE)

        #get OP's desired format
        combi <- rep(seq_along(sets), each=m)
        data.frame(
            Group=x$Group[1],
            Combi=paste(x$Group[1], combi, sep="."),
            Value=unlist(sets))
    }))
})

#final output
do.call(rbind, combiLs)

另一種可能的data.table實現同時使用choosecombn

res <- setDT(dat)[, {
        idx <- seq_along(Value)[-c(1, .N)]
        list(
            Set=paste0(Group[1], ".", unlist(lapply(idx, function(m) rep(seq_len(choose(.N, m)), each=m)))),
            Value=unlist(lapply(idx, function(m) as.vector(combn(Value, m))))
        )
    }, by=Group]

res[, Combi := unlist(Map(rep, x=seq_along(rle(Set)$values), each=rle(Set)$lengths))]

數據:

dat <- data.frame(Group=c(rep(1,4), rep(2,3)), Value=c("A","B","C","D","A","B","C"))
dat

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM