2015-11-27 70 views
3

背景:

我處理的一個組合問題在R.對於套我需要生成每一套都對不產生重複一個給定的名單。有效地與工作組中的R

實施例:

initial_list_of_sets <- list() 
initial_list_of_sets[[1]] <- c(1,2,3) 
initial_list_of_sets[[2]] <- c(2,3,4) 
initial_list_of_sets[[3]] <- c(3,2) 
initial_list_of_sets[[4]] <- c(5,6,7) 
get_pairs(initial_list_of_sets) 
# should return (1 2),(1 3),(2 3),(2 4),(3 4),(5 6),(5 7),(6 7) 

請注意,(3 2)不包括在結果中,因爲它在數學上等於(2 3)。到目前爲止

我的(工作,但效率不高)的方法:

# checks if sets contain a_set 
contains <- function(sets, a_set){ 
    for (existing in sets) { 
    if (setequal(existing, a_set)) { 
     return(TRUE) 
    } 
    } 
    return(FALSE) 
} 

get_pairs <- function(from_sets){ 
    all_pairs <- list() 
    for (a_set in from_sets) { 
    # generate all pairs for current set 
    pairs <- combn(x = a_set, m = 2, simplify = FALSE) 
    for (pair in pairs) { 
     # only add new pairs if they are not yet included in all_pairs 
     if (!contains(all_pairs, pair)) { 
     all_pairs <- c(all_pairs, list(pair)) 
     } 
    } 
    } 
    return(all_pairs) 
} 

我的問題:

正如我處理的數學套我不能使用%in%運營商,而不是我contains功能,因爲那麼(2 3)和(3 2)將是不同的對。但是,對contains中的所有現有集進行迭代似乎效率很低。有沒有更好的方法來實現這個功能?

+0

是的!我會接受你的回答。我想了解R如何在幕後快速實現...... – fab

+1

在循環中,每當有新值添加時,就會增加列表,這通常不是非常有效。我也嘗試在R中使用一些已經優化的函數(例如'lapply','unique')。 – A5C1D2H2I1M1N2O1R2T1

回答

1

也許你可以重寫你的get_pairs功能類似如下:

myFun <- function(inlist) { 
    unique(do.call(rbind, lapply(inlist, function(x) t(combn(sort(x), 2))))) 
} 

這裏有一個快速的時間比較。

n <- 100 
set.seed(1) 

x <- sample(2:8, n, TRUE) 
initial_list_of_sets <- lapply(x, function(y) sample(100, y)) 

system.time(get_pairs(initial_list_of_sets)) 
# user system elapsed 
# 1.964 0.000 1.959 
system.time(myFun(initial_list_of_sets)) 
# user system elapsed 
# 0.012 0.000 0.014 

如果需要,可以按split矩陣按行獲取您的列表。

如:

myFun <- function(inlist) { 
    temp <- unique(do.call(rbind, lapply(inlist, function(x) t(combn(sort(x), 2))))) 
    lapply(1:nrow(temp), function(x) temp[x, ]) 
}