这可能是不可能的,但到目前为止谷歌已经让我失望,所以我希望其他人可能有一些见解。对不起,如果之前有人询问过。
背景是,我有一个关于不同城市的信息数据库,所以像年份一样,名称,人口,污染,犯罪等。我查询它以按城市汇总数据并将结果输出到表格。这很好。
下一步是我在数据集上运行R中的kmeans()函数来查找集群,在测试中我发现5个集群几乎总是一个很好的选择,通过&#34肘法"。
我遇到的问题是这些群集具有不同的含义/解释,因此我想用原始数据集中的每一行标记该行的解释,而不是群集号。因此,我不想用第3组"第3组来识别第2行,我想说"低人口,高犯罪率,低收入"。
如果R会以相同的顺序输出集群,那么假设集群5总是等同于人口较少,犯罪率高,收入较低的城市集群,这样可以正常工作,但它不会#39;吨。例如,如果您运行如下代码:
> 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表,然后按各种指标对表进行排序,每次最高/最低的数据被标记为这样,然后连接结果以标记级别。这可能有用,但并不优雅。
答案 0 :(得分:2)
我知道这是一个很老的帖子,但我现在才遇到它。我今天遇到了同样的问题,并根据Barker提出的建议来提出解决方案:
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
答案 1 :(得分:1)
通常k-means随机初始化几次以避免局部最小值。如果要生成有序的聚类,则必须在k-means算法停止工作后手动对它们进行排序。
答案 2 :(得分:1)
我自己没有这样做,所以我不确定它是否会奏效,但kmeans
有参数:
centers
- 群集数量,例如k,或一组初始(不同)群集中心。如果是数字,则选择x中随机的(不同)行作为初始中心。如果您基本知道群集应该在哪里(可能是通过从您匹配的数据集中获取群集中心),则可以使用它来初始化模型。这将使起始位置非随机,因此群集应保持相同的顺序。此外,作为额外的好处,将群集中心初始化到接近最终的位置可以加快群集速度。
修改强>
我刚刚使用kmeans
示例中的数据进行了检查,但是使用(1,1)
处的第一个数据点和(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
集群初始化则导致来回切换。如果您的群集具有一些近似的起始值(即,#34;低人口,高犯罪率,低收入&#34;的量化),这可能是您的初始化并为您提供所需的结果。
答案 3 :(得分:0)
在此示例中,将字母因子组归因于k均值聚类,从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]))
答案 4 :(得分:0)
此函数使用一维输入运行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