2015-06-29 101 views
4

是否有一種簡單的方法可以計算h中的最小值cut,它可生成給定最小大小的分組?R將樹形圖分割成最小大小的組

在這個例子中,如果我想集羣,每個至少十名成員,我應該h = 3.80去:

# using iris data simply for reproducible example 
data(iris) 
d <- data.frame(scale(iris[,1:4])) 
hc <- hclust(dist(d)) 
plot(hc) 

cut(as.dendrogram(hc), h=3.79) # produces 5 groups; group 4 has 7 members 

cut(as.dendrogram(hc), h=3.80) # produces 4 groups; no group has <10 members 

由於分裂的高度在hc$height給出,我可以創建一組候選的值使用hc$height + 0.00001,然後循環切割每一個。但是,我沒有看到如何解析dendrogram類中的簇大小members。例如,cut(as.dendrogram(hc), h=3.80)$lower[[1]]$members返回NULL,而不是66根據需要。

請注意,這是一個比Cutting dendrogram into n trees with minimum cluster size in R更簡單的問題,它使用包dynamicTreeCut;這裏我沒有指定樹的數量,只是最小的簇大小。 TYVM。

+1

作爲一個附註:成員是一個屬性 - 'attr(cut(as.dendrogram(hc),h = 3.80)$ lower [[1]],「members」)產量爲66. – lukeA

回答

1

這並不回答這個問題,但如果您決定循環訪問h,則可能對提取members有用。

盜竊和here

# Unnest the list/dendogram structure 
unnest <- function(x) { 
    if(is.null(names(x))) { 
    x 
    } 
    else { 
    c(list(all=unname(unlist(x))), do.call(c, lapply(x, unnest))) 
    } 
} 

# Extract the `members` attribute from each dendogram 
lapply(X = unnest(cut(as.dendrogram(hc), h=3.8)), FUN = attr, which = "members") 

輸出修改一些代碼:

# Please don't ask me why there are 2 dendograms stored 
# in the `$upper` list while `print` displays one 

$upper1 
[1] 2 

$upper2 
[1] 2 

$lower1 
[1] 66 

$lower2 
[1] 11 

$lower3 
[1] 24 

$lower4 
[1] 49 
+0

這是一個有用的遞歸,謝謝。 – C8H10N4O2

3

感謝@Vlo和@lukeA我能夠實現一個循環。不過,我只是將其發佈到一個起點上,並且肯定會打開一個更優雅的解決方案。

unnest <- function(x) { # from Vlo's answer 
    if(is.null(names(x))) x 
    else c(list(all=unname(unlist(x))), do.call(c, lapply(x, unnest))) 
} 

cuts <- hc$height + 1e-9 

min_size <- 10 
smallest <- 0 
i <- 0 

while(smallest < min_size & i <= length(cuts)){ 
    h_i <- cuts[i <- i+1] 
    if(i > length(cuts)){ 
    warning("Couldn't find a cluster big enough.") 
    } 
    else smallest <- 
      Reduce(min, 
        lapply(X = unnest(cut(as.dendrogram(hc), h=h_i)$lower), 
         FUN = attr, which = "members")) # from lukeA's comment 
} 
h_i # returns desired output: [1] 3.79211 
2

此功能在dendextend包與heights_per_k.dendrogram功能(加載dendextendRcpp功能時其也具有較快的C++實現)提供。

## Not run: 
hc <- hclust(dist(USArrests[1:4,]), "ave") 
dend <- as.dendrogram(hc) 
heights_per_k.dendrogram(dend) 
##  1  2  3  4 
##86.47086 68.84745 45.98871 28.36531 

作爲旁註,所述dendextend包具有用於一個系統樹S3 cutree.dendrogram方法(其工作非常類似於cutree爲hclust對象)。

+0

感謝您的答案(並創建了dendextend包,+1)。我回滾了你的標籤編輯,因爲我的問題本身不是一個[dendextend]問題,雖然它可能很方便,但[dendextend]並不是唯一的解決方案。 [Context](http://meta.stackoverflow.com/questions/252079/tagging-a-question-based-on-its-answers) – C8H10N4O2

+0

Hello @ C8H10N4O2。我很高興你喜歡d​​endextend :)(任何獲得「V」票的機會?)。至於刪除標籤 - 我看到你鏈接到的元。在我看來,因爲dendextend是一個旨在回答這些問題的軟件包 - 我寧願當人們看着dendextend標籤時他們會找到這個解決方案。即:http://meta.stackexchange.com/questions/26913/should-i-retag-a-question-with-a-tag-that-is-based-on-the-answer-and-not-the- que/26914#26914 既然這是你的Q--那顯然是你的決定。 –