【问题标题】:kmeans clustering using PL/R in postgresql在 postgresql 中使用 PL/R 进行 kmeans 聚类
【发布时间】:2014-03-07 17:19:48
【问题描述】:

我正在尝试在 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

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

【问题讨论】:

    标签: r postgresql cluster-analysis plr


    【解决方案1】:

    请先阅读K-means documentation

    您会注意到 K-means 包含一个随机元素 - 这就是导致您的输出按行显示不同集群 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。然后,您可以在 id 上将集群 ID 加入到您的表中。

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

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

    【讨论】:

    • 感谢您的回复 ... set.seed 有效,我正在研究聚合函数 ....
    猜你喜欢
    • 1970-01-01
    • 2015-02-05
    • 2019-11-27
    • 2012-04-21
    • 2019-01-06
    • 2017-11-23
    • 2021-11-27
    • 2016-06-04
    • 1970-01-01
    相关资源
    最近更新 更多