#r #k-means
#r #k-означает
Вопрос:
Это может быть невозможно, но Google пока меня подвел, поэтому я надеюсь, что у кого-то еще может быть некоторое представление. Извините, если об этом спрашивали раньше.
Предыстория в том, что у меня есть база данных с информацией о разных городах, например, о названии, населении, загрязнении, преступности и т. Д. По годам. Я запрашиваю его для агрегирования данных по каждому городу и вывода результата в таблицу. Это работает нормально.
Следующим шагом я запускаю функцию kmeans() в R в наборе данных для поиска кластеров, в ходе тестирования я обнаружил, что 5 кластеров почти всегда являются хорошим выбором с помощью «метода локтя».
Проблема, с которой я сталкиваюсь, заключается в том, что эти кластеры имеют разные значения / интерпретации, поэтому я хочу пометить каждую строку в исходном наборе данных интерпретацией кластера для этой строки, а не номером кластера. Поэтому я не хочу отождествлять строку 2 с «кластером 5», я хочу сказать «низкая численность населения, высокая преступность, низкий доход».
Если R будет выводить кластеры в том же порядке, скажем, если кластер 5 всегда приравнивается к кластеру городов с «низким населением, высокой преступностью, низким доходом», это будет работать нормально, но это не так. Например, если вы выполняете код, подобный этому:
> a = kmeans(city_date,centers=5)
> b = kmeans(city_date,centers=5)
> c = kmeans(city_date,centers=5)
Запуск этого кода:
a$centers
b$centers
c$centers
Все кластеры будут содержать один и тот же набор данных, но номер кластера будет другим. Итак, если у меня есть таблица сопоставления в SQL с номером кластера и интерпретацией, она не будет работать, потому что, когда я однажды ее запущу, кластер «низкая численность населения, высокая преступность, низкий доход» может иметь значение 5, а в следующий раз это может быть 2, следующие 4 и т. Д.
Я пытаюсь выяснить, есть ли способ сохранить согласованность выходных данных. Набор данных обновляется, поэтому он даже не будет одинаковым каждый раз, и поскольку R не поддерживает согласованный порядок кластеров даже с одним и тем же набором данных, мне интересно, будет ли это вообще возможно.
Спасибо за любую помощь, которую кто-либо может предоставить. С моей стороны, моя текущая идея состоит в том, чтобы вывести данные $ centers в таблицу SQL, затем упорядочить таблицу по различным метрикам, каждый раз, когда тот, у которого самый высокий / самый низкий, помечается как таковой, а затем объединить результаты для обозначения уровня. Это может работать, но не очень элегантно.
Ответ №1:
Я знаю, что это очень старый пост, но я наткнулся на него только сейчас. Сегодня у меня была такая же проблема, и я адаптировал предложение Баркера, чтобы найти решение:
library(dplyr)
# create a random data frame
df <- data.frame(id = 1:10, obs = sample(0:500, 10))
# use kmeans a first time to get the centers
centers <- kmeans(df$obs, centers = 3)$centers
# order the centers
centers <- sort(centers)
# call kmeans again but this time passing the centers calculated in the previous step
clusteridx <- kmeans(df$obs, centers = centers)$cluster
Не очень элегантно, но это работает. Вектор clusteridx всегда будет возвращать номер кластера на основе центров в порядке возрастания.
Это также можно свернуть в одну строку, если вы предпочитаете:
clusteridx <- kmeans(df$obs, centers = sort(kmeans(df$obs, centers = 3)$centers))$cluster
Ответ №2:
Обычно k-средние инициализируются случайным образом несколько раз, чтобы избежать локальных минимумов. Если вы хотите упорядочить результирующие кластеры, вы должны упорядочить их вручную после того, как алгоритм k-means перестанет работать.
Комментарии:
1. Спасибо! Итак, меня интересует порядок вручную, это будет частью конвейера данных, поэтому я не могу просматривать кластеры при каждом запуске. Я бы предпочел сделать что-то на R или найти какой-нибудь не SQL-способ сохранения последовательности кластерных порядков, если это возможно.
2. Извините, я не могу помочь с R.
Ответ №3:
Я сам этого не делал, поэтому я не уверен, что это сработает, но kmeans
имеет параметр:
centers
— либо количество кластеров, скажем, k, либо набор начальных (отдельных) центров кластера. Если число, случайный набор (отдельных) строк в x выбирается в качестве начальных центров.
Если вы знаете, в основном знаете, где должны быть кластеры (возможно, путем получения центров кластеров из набора данных, с которым вы сопоставляете), вы можете использовать это для инициализации модели. Это сделало бы начальные местоположения неслучайными, поэтому кластеры должны оставаться в том же порядке. Кроме того, в качестве дополнительного преимущества инициализация центров кластеров вблизи того места, где они окажутся, должна ускорить кластеризацию.
Редактировать
Я только что проверил, используя данные из kmeans
примера, но инициализируя с первой точкой данных at (1,1)
и второй at (0,0)
(средства распределений, используемые для создания кластеров), как показано ниже.
x <- rbind(matrix(rnorm(100, sd = 0.3), ncol = 2),
matrix(rnorm(100, mean = 1, sd = 0.3), ncol = 2))
colnames(x) <- c("x", "y")
(cl <- kmeans(x, matrix(c(1,0,1,0),ncol=2)))
plot(x, col = cl$cluster)
points(cl$centers, col = 1:2, pch = 8, cex = 2)
После повторных запусков я обнаружил, что первый кластер всегда находился в правом верхнем углу, а второй — в левом нижнем углу, где инициализация с 2
помощью кластеров приводила к переключению назад и вперед. Если у вас есть некоторые приблизительные начальные значения для ваших кластеров (т. Е. Количественная оценка для «низкой численности населения, высокой преступности, низкого дохода»), это может быть вашей инициализацией и дать вам желаемые результаты.
Ответ №4:
Эта функция запускает kmeans с одномерным вводом и возвращает обычный объект «kmeans» с разумно пронумерованными кластерами, без необходимости запускать kmeans дважды.
ordered_kmeans = function(x, centers, iter.max = 10, nstart = 1,
algorithm = c("Hartigan-Wong", "Lloyd", "Forgy",
"MacQueen"),
trace = FALSE,
desc = TRUE) {
if (NCOL(x) > 1) {
stop("only one-dimensional inputs are allowed")
}
k = kmeans(x = x, centers = centers, iter.max = iter.max, nstart = nstart,
algorithm = algorithm, trace = trace)
centers_ind = order(k$centers, decreasing = desc)
centers_ord = setNames(seq_along(k$centers), nm = centers_ind)
k$cluster = unname(centers_ord[as.character(k$cluster)])
k$centers = matrix(k$centers[centers_ind], ncol = 1)
k$withinss = k$withinss[centers_ind]
k$size = k$size[centers_ind]
k
}
Пример использования:
vec = c(20.28, 9.49, 7.14, 2.48, 2.36, 1.82, 1.3, 1.26, 1.11, 0.98,
0.81, 0.73, 0.66, 0.63, 0.57, 0.53, 0.44, 0.42, 0.38, 0.37, 0.33,
0.29, 0.28, 0.27, 0.26, 0.23, 0.23, 0.2, 0.18, 0.16, 0.15, 0.14,
0.14, 0.12, 0.11, 0.1, 0.1, 0.08)
# For comparispon
set.seed(1)
k = kmeans(vec, centers = 3); k
set.seed(1)
k = ordered_kmeans(vec, centers = 3); k
set.seed(1)
k = ordered_kmeans(vec, centers = 3, desc = FALSE); k
Ответ №5:
Вот пример, в котором вы приписываете группы буквенных коэффициентов кластерам k-means, упорядоченным от A — низкий до C — высокий. Параметры могут быть изменены в соответствии с имеющимися у вас данными.
df <- data.frame(id = 1:10, obs = sample(0:500, 10))
km <- kmeans(df$obs, centers = 3)
km.order <- as.numeric(names(sort(km$centers[,1])))
names(km.order) <- toupper(letters)[1:3]
km.order <- sort(km.order)
clus.order <- factor(names(km.order[km$cluster]))