r - 在 postgresql 中使用 PL/R 进行 kmeans 聚类

标签 r postgresql cluster-analysis plr

我正在尝试在 PL/R 中使用 kmeans 函数。 我创建了下表

CREATE TABLE EMP (NAME1 TEXT, AGE SMALLINT, SALARY NUMERIC );

INSERT INTO EMP VALUES 
('Joe', 41, 55000),
('Jill', 27, 25000),
('Jack', 31, 45000),
('Joker', 65, 20000),
('Joy', 22, 31000),
('Jane', 72, 35000),
('Jackson', 42, 65000),
('Jessica', 23, 37000);

下面给出了我的聚类函数

CREATE OR REPLACE FUNCTION CLUS(sal NUMERIC[])
RETURNS INTEGER[] AS
$BODY$

a <- NA
a = kmeans(sal, 3)$cluster
return(a)

$BODY$
LANGUAGE 'plr' ;

当我执行下面的查询时

SELECT * , CLUS(ARRAY (SELECT SALARY FROM EMP ORDER BY SALARY)) AS CLUSTER_ID from emp order by salary;

我的输出是

name1   age salary  cluster_id
Joker   65  20000   {3,3,2,2,2,2,1,1}
Jill    27  25000   {2,2,2,2,2,3,3,1}
Joy     22  31000   {3,3,2,2,2,2,1,1}
Jane    72  35000   {1,1,1,1,1,2,2,3}
Jessica 23  37000   {1,1,2,2,2,2,3,3}
Jack    31  45000   {2,2,3,3,3,3,1,1}
Joe     41  55000   {1,1,3,3,3,3,2,2}
Jackson 42  65000   {2,2,3,3,3,3,1,1}

我面临的问题是,每次评估一行时,集群都会发生变化,我想要以下输出......

name1   age salary  cluster_id
Joker   65  20000   3
Jill    27  25000   3
Joy     22  31000   2
Jane    72  35000   2
Jessica 23  37000   2
Jack    31  45000   2
Joe     41  55000   1
Jackson 42  65000   1

请告诉我是否可以用更好更简单的方式完成

最佳答案

请阅读K-means documentation首先。

您会注意到 K-means 涉及一个随机元素 - 这就是导致您的输出按行显示不同 cluster-id 的原因。

参见 here了解如何使用 set.seed 在给定相同输入的情况下在每次执行时复制相同的聚类结果。

您做错的第二件事是您实现 CLUS 函数的方式以及调用它的方式。

让我通过展开您正在运行的查询来突出显示该问题:

SELECT 
* 
,CLUS(ARRAY (SELECT SALARY FROM EMP ORDER BY SALARY)) AS CLUSTER_ID 
from emp 
order by salary;

name    age salary  inputForClus                                         cluster_id
Joker   65  20000   {20000,25000,31000,35000,37000,45000,55000,65000}   {3,3,2,2,2,2,1,1}
Jill    27  25000   {20000,25000,31000,35000,37000,45000,55000,65000}   {2,2,2,2,2,3,3,1}
Joy     22  31000   {20000,25000,31000,35000,37000,45000,55000,65000}   {3,3,2,2,2,2,1,1}
Jane    72  35000   {20000,25000,31000,35000,37000,45000,55000,65000}   {1,1,1,1,1,2,2,3}
Jess    23  37000   {20000,25000,31000,35000,37000,45000,55000,65000}   {1,1,2,2,2,2,3,3}
Jack    31  45000   {20000,25000,31000,35000,37000,45000,55000,65000}   {2,2,3,3,3,3,1,1}
Joe     41  55000   {20000,25000,31000,35000,37000,45000,55000,65000}   {1,1,3,3,3,3,2,2}
Jack    42  65000   {20000,25000,31000,35000,37000,45000,55000,65000}   {2,2,3,3,3,3,1,1}

请注意每一行的 inputForClus 列是如何相同的。由于前面提到的随机元素,簇 ID 逐行变化。

在您的案例中应用 k-means 的正确方法是编写一个函数,它接受一个 id 列和一个数字 array。然后该函数将返回一个包含两列 idcluster-id 的表。您可以将您的函数实现为一个retruns table。然后,您可以将 cluster-ids 加入到 id 上的表中。

首先搜索 Postgresql 文档以了解如何编写表返回函数。

另一种方法可能是将 k-means 函数指定为 aggregate 函数。

关于r - 在 postgresql 中使用 PL/R 进行 kmeans 聚类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21676153/

相关文章:

r - 使用 read_delim 解析分秒日期

R:具有多个参数的 integrate() 函数

image - 对 1000 张图像进行聚类以找到具有更大相似性的图像组

r - 聚类预测

algorithm - 估计两个集群之间的最小距离

r - 将 YearQtr 系列转换为月末日期

r - 按序列分割向量

PostgreSQL 重用更新计算

SQL:在已知问题时获取问题的所有标签

java - 在 JOOQ 中,如果我直接使用底层连接,我的事务状态是否保持?