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

SAS program, How to do the calculation based on two tables without IML

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

任务table

工程师table:

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

距离:

由于 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)

     }
   }

好吧,GEODIST 函数就是这样做的。

假设 table 称为 tasksengineers 具有您在 post 中呈现的结构(为了将来参考,我们宁愿将它们作为文本而不是images), 你可以用下面的方法获得第三个 table:

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;

这将为您提供一个 table,其中包含以下列

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_idE_n_xE_n_y是工程师的坐标n .

然后只需逐行处理数据集,将变量输入 geodist 函数即可。

这与 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;

也许我遗漏了一些东西,但交叉连接也应该可以很好地与 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;