5

有没有一种简单的方法来计算产生给定最小大小的分组的hin最小值?cut

在这个例子中,如果我想要每个至少有 10 个成员的集群,我应该使用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,然后循环遍历每个候选值。但是,我看不到如何将集群大小解析membersdendrogram类。例如,根据需要cut(as.dendrogram(hc), h=3.80)$lower[[1]]$members返回NULL,而不是 66。

请注意,这是一个比在使用包的 R 中将树状图切割成具有最小簇大小的 n 棵树dynamicTreeCut更简单的问题;这里我没有指定树的数量,只是最小集群大小。TYVM。

4

3 回答 3

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
于 2015-06-29T21:27:10.000 回答
2

此功能在带有函数的dendextend包中可用(在加载dendextendRcppheights_per_k.dendrogram函数时,它还具有更快的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 包有一个cutree.dendrogram用于树状图的 S3 方法(其工作方式与用于 hclust 对象的 cutree 非常相似)。

于 2015-07-11T15:20:44.307 回答
1

这不能回答问题,但members如果您决定遍历h.

从这里窃取和修改一些代码

# 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
于 2015-06-29T20:55:35.143 回答