2015-06-29 10 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, а затем прорезайте сквозные разрезы на каждом из них. Однако я не вижу, как анализировать размер кластера members из класса dendrogram. Например, 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

Это не отвечает на вопрос, но может оказаться полезным для извлечения members, если вы решите пройти через h.

Кража и изменение код из 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 функции (которая также имеет более быструю реализацию C++ при загрузке функции dendextendRcpp).

## 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 метод дендрограмм (который работает очень похоже на cutree для объектов hclust).

+0

Благодарим вас за ответ (и за создание пакета dendextend, +1). Я отменил редактирование тега, потому что мой вопрос не является вопросом [dendextend] как таковой, и, хотя это может быть удобно, [dendextend] не является единственным решением. [Контекст] (http://meta.stackoverflow.com/questions/252079/tagging-a-question-based-on-its-answers) – C8H10N4O2

+0

Привет @ C8H10N4O2. Я рад, что вам нравится dendextend :) (любой шанс на голосование «V»?). Что касается удаления тега - я вижу мета, с которой вы связаны. На мой взгляд, поскольку dendextend - это пакет, предназначенный для ответа на такие вопросы - я бы предпочел, чтобы, когда люди смотрят на тег dendextend, они найдут это решение. т.е.: http://meta.stackexchange.com/questions/26913/should-i-retag-a-question-with-a-tag-that-is-based-on-thewer-and-not-the- que/26914 # 26914 Поскольку это ваш Q - это, очевидно, ваше решение. –