2015-06-29 61 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--那显然是你的决定。 –