SAS:计算每个客户与表中所有其他客户的平均(欧几里德)距离

时间:2014-01-28 23:03:11

标签: sas distance euclidean-distance

我有一个拥有以下属性的6万客户的SAS数据集:
1)客户编号
2)X坐标
3)Y坐标
4)实体店访问

我需要计算每个客户与表中所有其他客户的平均加权距离,其中每个距离按比较客户的访问次数加权。例如,客户A和A之间的距离。客户B为10.然后,我们将根据客户B的访问次数(2)对该距离进行加权,该次数等于5.此过程将对表中的所有其他客户重复,然后我们将对每个60k的加权距离进行平均客户。

我认为执行此操作的蛮力方式是笛卡尔连接(即创建一个60k x 60k = 36亿记录表),但这可能会耗尽内存或崩溃SAS。我还想过将其分解为更易于管理的笛卡尔连接(即10 x 60K = 600k x 6000次迭代,但这可能非常耗时 - 可能是我唯一的选择)。我猜你们/ gals知道一个更好的方法来做到这一点!

我感谢您的所有建议。

谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

坏消息,没有办法加快这个计算(我知道)。

好消息是如果您使用笛卡尔积,SAS不会崩溃或内存不足。其他好消息是在数据步骤中执行此操作比在PROC SQL中执行此操作更快。

data test;
do cn=1 to 64000;
    x = ceil(Ranuni(13)*100);
    y = ceil(ranuni(13)*100);
    visits = max(1,round(rannor(12)*3 + 8,1));
    output;
end;
run;

sasfile test load;

data ave_dist(keep=cn ave_dist);
set test end=last;

dist=0;
td= 0;
total_visits=0;
do i=1 to n;
    set test(rename=(cn=cn_2 x=x_2 y=y_2) drop=visits) point=i nobs=n;

    if cn ^= cn_2 then do;
        xx = (x-x_2);
        yy = (y-y_2);
        total_visits = total_visits + visits;
            dist = sqrt(xx*xx + yy*yy);
        if dist^= 0 then
            dist = 1/dist;
    else 
        dist = 100; /*Adjust to something that makes sense to your data*/
        td = visits*dist + td;
    end;
end;

ave_dist = td / total_visits;   
output;

run;

sasfile test close;

我倒转了距离计算。你希望小距离获得更高的分数。我认为这是一个真正的访问加权平均值。

在我的笔记本电脑上运行大约需要13分钟。

答案 1 :(得分:1)

如果您的客户群将<100k,那么PROC DISTANCE可能会有所帮助。使用@DomPazz创建的数据集,您可以运行以下代码并检查结果。在这种情况下,我只是尝试了以16secs运行的前10K客户。不要让那个愚弄你的虚假安全感。当你加倍的时候。客户所花费的时间是4倍。 (实际时间:10K - 16秒,20K - 47秒,40K - 3分钟......)

此过程生成NxN方阵(其中N是输入数据集中的客户编号)。您可以尝试并尝试并查看SAS在什么时候遇到RAM内存问题(确保有足够的硬盘空间,至少大约为1.10 * NxN * 8字节)。 矩阵中的每个单元代表i客户(在行中)与第j个客户(在列中)的距离。一旦达到距离,就可以将相应的距离乘以客户的访问量并取平均值。

proc distance data = test(obs = 100)
OUT=test_distances(compress = binary)
METHOD= EUCLID shape = SQUARE 
UNDEF=1000000
VARDEF=wdf;
var INTERVAL(x y)
;
copy cn visits;
run;

data avg_dist;
set train_distances;
array dist{*} dist:;
prod=0;
do i = 1 to dim(dist);
prod = visits*dist{i}+prod;
end;

avg_dist=prod/dim(dist);

dims=dim(dist);

drop i dist:
;
run;
proc sql;
drop table test_distances;
quit;

您要解决的问题类型通常称为k-nearest neighbour问题。在这个领域已经进行了数十年的研究,并且通常使用特殊的数据结构(例如Kd-trees)来解决这些问题。大多数情况下,人们有兴趣回答诸如who are the top-10 (or K) closest customers to this customer I'm interested in?之类的问题。另一个非常有效解决这类问题的程序是PROC PMBR,它同时支持kd-tree和SAS的专有结构Rd-tree {1}} - 查阅 - 您只能在4.3天内找到SAS Eminer的pdf文档

当您需要计算N * N项目之间的距离时,您会遇到麻烦。 通过阅读评论中的项目描述,您需要的不是计算每个客户与其他客户之间的距离,而是计算每个客户与每个商店之间的距离。

这将大大提高您的查询性能,因为问题的维度大大降低。

假设你有N个顾客和S商店,那么你只需要计算N * S点之间的距离。 (一个简单的数据步骤将完成工作,因为不需要笛卡尔积或专门的数据结构)

从那里你可以看到,对于S中的每家商店来说,在该商店购买的客户中有多少比例居住在1KM,2KM,3KM ....

然后你可以得出答案,如80%住在1公里内,15%住在2公里以内等......