SAS程序,如何在没有IML的情况下基于两个表进行计算

时间:2017-10-19 19:47:27

标签: sas sas-macro

我一直在为sas中的某些矩阵计算而苦苦挣扎。 我有两个表,它们都包含经度和纬度信息

任务表

Public-key cryptography

工程师表:

enter image description here

我的输出目标是任务和工程师之间的距离

的距离:

enter image description here

由于SAS / IML的额外费用,我没有在内部使用它。有人有经验怎么做吗?

P.S。 R中的代码很简单如下

   distances <- matrix(nrow = NROW(tasks), ncol = NROW(cses))
   for (i in 1:NROW(tasks)){
     for(j in 1:NROW(cses)){
       distances[i,j] <- distm (c(tasks$CUST_LNG_X[i], tasks$CUST_LAT_Y[i]), c(cses$LNG_X[j], cses$LAT_Y[j]), fun = distHaversine)

     }
   }

3 个答案:

答案 0 :(得分:1)

GEODIST函数可以做到这一点。

假设名为tasksengineers的表格具有您在帖子中显示的结构(以供将来参考,我们宁愿将其作为文本而不是图像),您可以获取第三个表格以下内容:

proc sql;
create table engineers_2 as
select compress(id||'_y') as id
      ,geo_y as geo
from engineers
union
select compress(id||'_x') as id
      ,geo_x as geo
from engineers
order by id
;
quit;

proc transpose data=engineers_2 out=t_engineers(drop=_name_);
var geo;
id id;
run;

proc sql;
create table want as
select *
from tasks
    ,t_engineers
;
quit;

这将为您提供一个包含以下列的表

task_id geo_y geo_x E_1_x E_1_y E_2_x E_2_y E_3_x E_3_y

其中geo_ygeo_x是任务task_id的坐标,E_n_xE_n_y是工程师n的坐标。< / p>

然后只需要逐行处理数据集,在geodist函数中提供变量。

答案 1 :(得分:1)

也许我错过了一些东西,但是交叉连接也应该可以正常使用GEODIST函数,然后进行转置以使其变宽。每个文件中有多少点并不重要,不过我认为如果它足够大,SQL可能会因内存而错误。

proc sql;
create table want as
select task_id as col1, id as col2, geodist(a.x, a.y, b.x, b.y) as distance
from tasks as a , engineers as b;
quit;

proc transpose data=want out=want_wide ;
by col1;
id col2;
var distance;
run;

答案 2 :(得分:0)

这与user2877959非常相似。

data tasks;
input Task_ID $ Y X;
datalines;
T_1 41.65 -74.08
T_2 32.48 -86.46
;
run;

%let n=2; /*This is the number of engineer points*/

data engineers;
input ID $ Y X;
datalines;
E_1 40.92 -81.31
E_2 39.98 -74.87
;
run;

我的不同之处在于创建X_Y_是后缀。这将使事情变得更容易。我在数据步骤中进行此操作然后进行转置。使用SQL也可以。

data engineers;
set engineers;
X_NAME = catt("X_",id);
Y_NAME = catt("Y_",id);
run;

proc transpose data=engineers(keep=x_name x) out=e_x;
id x_name;
run;

proc transpose data=engineers(keep=y_name y) out=e_y;
id y_name;
run;

/*This puts the engineer data into 1 record in a single table*/
data engineers;
merge e_y e_x;
drop _name_;
run;

proc sql noprint;
create table want as
select a.*,
       b.*
    from tasks a,
         engineers b;
quit;

最后一步是计算距离。我们可以使用DATA STEP数组来帮助处理。

data want;
set want;
array E_[&n];
array X_E_[&n];
array Y_E_[&n];

do i=1 to &n;
    E_[i] = geodist(x,y,x_e_[i],y_e_[i]);
end;

drop X: Y: i;
run;