Нахождение количества идентичных групп - PullRequest
2 голосов
/ 22 мая 2019

Рассмотрим проблему кластеризации, когда известны истинные метки классов (скажем, g).

Предположим, p обозначает прогнозируемые метки кластера (могут быть получены любым подходом кластеризации).

Итак, и g, и p разделяют набор данных в некоторых группах, хотя количество групп не обязательно должно быть одинаковым в двух случаях.

Среди этих двух наборов групп в некоторыхслучаи, когда одна группа на g будет идентична другой группе на p, хотя их метки в двух случаях могут быть разными.Я хочу узнать количество таких групп, то есть я хочу найти количество случаев, когда метод кластеризации может точно определить класс.

Я понимаю, что это не стандартный способ оценки кластеризации (RandРекомендуется индекс, индекс Данна и т. Д.), Но я заинтересован в этом.Я также понимаю, что это число будет очень маленьким в большинстве реальных данных, может быть даже 0, но набор данных, с которыми я сейчас работаю, имеет большое количество (около 1500) классов с наибольшим количеством наблюдений.в одном классе не более 15. Таким образом, в этом случае это число, вероятно, будет довольно большим.

Вот воспроизводимый пример и моя попытка (работа) по решению:

# true labels
g <- c(1, 1, 2, 2, 2, 1, 3, 3, 3, 4)

# predicted labels
p <- c(3, 3, 1, 1, 1, 3, 4, 4, 1, 2)

# correctly detected groups
n_correct <- 2 # (1st class and 3rd cluster), (4th class and 2nd cluster)

# attempt
distinct_class_labels <- unique(x = g)
counter <- 0
for (i in seq_along(along.with = distinct_class_labels))
{
  cluster_labels_of_obs_in_ith_class <- subset(x = p,
                                               subset = (g == distinct_class_labels[i]))
  unique_cluster_labels_of_obs_in_ith_class <- unique(x = cluster_labels_of_obs_in_ith_class)
  if (length(x = unique_cluster_labels_of_obs_in_ith_class) == 1)
  {
    class_labels_of_obs_in_this_cluster <- subset(x = g,
                                                  subset = (p == unique_cluster_labels_of_obs_in_ith_class))
    if (length(x = unique(x = class_labels_of_obs_in_this_cluster)) == 1)
    {
      counter <- (counter + 1)
    }
  }
}
counter
#> [1] 2

Создано в 2019-05-22 с помощью пакета Представить (v0.3.0)

Это работает правильно, но требует времени (а я неткак этот метод).Я полагаю, можно использовать dplyr::group_by с обоими g и p по отдельности и как-то сравнивать группы этих двух объектов.Я думаю, что есть и другие лучшие подходы к этому, и я буду очень признателен за такие ответы.

Спасибо.

Ответы [ 2 ]

2 голосов
/ 22 мая 2019

Если вас также интересует комбинация правильно обнаруженных групп, вы можете попробовать это

library(tidyverse)

tibble(g = g, p=p) %>%
  distinct(g,p) %>% # unique combinations of g and p
  add_count(g, name="g_count") %>% # count how often each class/label occurs in g and p. When it is unambiguous assigned it should be 1
  add_count(p, name="p_count") %>%
  filter(g_count == 1 & p_count == 1) %>%
  select(g,p)

# A tibble: 2 x 2
      g     p
  <dbl> <dbl>
1     1     3
2     4     2

Количество строк (вы можете использовать nrow()) даст вам количество правильно обнаруженных групп

1 голос
/ 22 мая 2019

Преобразуйте g и p в factor с levels, указанным на основе их вхождения в вектор, и подсчитайте частоты, которые соответствуют.

sum(table(factor(p, levels = unique(p))) == table(factor(g, levels = unique(g))))
#[1] 2

Чтобы понять, см.

table(factor(p, levels = unique(p)))

#3 1 4 2 
#3 4 2 1 
table(factor(g, levels = unique(g)))

#1 2 3 4 
#3 3 3 1 

Мы можем игнорировать метки (поскольку метки групп не совпадают) и фокусироваться только на частоте.Мы можем видеть, что первое и четвертое значение имеют одинаковую частоту, отсюда отсчет 2.

Если вы хотите узнать, какие группы похожи, вы можете сделать

inds <- table(factor(p, levels = unique(p))) == table(factor(g, levels = unique(g)))
unique(p)[inds]
#[1] 3 2
unique(g)[inds]
#[1] 1 4

Это говоритэта группа 3 в p аналогична группе 1 в g и одинакова для 2 и 4 соответственно.


Прежде чем решить это с помощью table, я сделал это с split, хотя основная логика та же.

sum(lengths(split(p, factor(p, levels = unique(p)))) == 
    lengths(split(g, factor(g, levels = unique(g)))))

РЕДАКТИРОВАТЬ

Если есть вероятность дисбаланса классов, нам нужно объединить уровни, чтобы включить все.Например,

g1 <- c(g, 5)
p1 <- c(p, 1)


sum(table(factor(p1, levels = unique(c(p1, g1)))) ==  
    table(factor(g1, levels = unique(c(g1, p1)))))
#[1] 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...