k表示在postgresql中使用PL / R进行聚类

时间:2014-02-10 11:38:22

标签: 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

如果能以更好,更简单的方式完成,请告诉我

1 个答案:

答案 0 :(得分: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的函数。然后该函数将返回一个表,该表有两列id&amp; cluster-id。您可以将您的函数实现为retruns table。然后,您可以在id上将群集ID重新加入到您的表格中。

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

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