SAS中的最近邻居

Nearest neighbour in SAS

我有一个包含纬度、经度和海拔数据的点数据集。我想通过使用任意两个给定点(2d 或 3d)之间的距离来识别给定点的最近邻居。有人可以建议 SAS 中用于此类地理空间数据分析的不同方法和示例 SAS 代码吗?谢谢。

下面是一个通过使用 SQL 计算最近邻的例子(在某处的 SAS 帮助文件中给出):

options ls=80 ps=60 nodate pageno=1 ;
data stores;
  input Store $ x y;
  datalines;
store1 5 1
store2 5 3
store3 3 5
store4 7 5
;
data houses;
   input House $ x y;
   datalines;
house1 1 1
house2 3 3
house3 2 3
house4 7 7
;

options nodate pageno=1 linesize=80 pagesize=60;

proc sql;
   title 'Each House and the Closest Store';
   select house, store label='Closest Store',
          sqrt((abs(s.x-h.x)**2)+(abs(h.y-s.y)**2)) as dist
              label='Distance' format=4.2
      from stores s, houses h

    group by house
      having dist=min(dist);
quit;

您最好的选择是查看聚类程序,因为 KNN 样式聚类非常接近您想要的(至少聚类分析可以让您找到 'set' 个邻居来检查)。 PROC MODECLUS、PROC FASTCLUS、PROC CLUSTER 在这里都为您提供了一些价值,PROC DISTANCE 在某些情况下用作上述输入也是如此。您想要使用的确切内容取决于您的需要和您的 speed/size 约束(PROC CLUSTER 对于大型数据集非常慢,但通常会提供更有用的结果)。

我写了 2 个宏来完成这个!

第一个宏 获取一个输入 gps 位置,并将纬度和经度用作 "neighbor" 位置数据集的新变量设置值。计算所有距离和 select 最小值并存储在临时数据集中。

second 通过输入数据集调用宏循环并传入单独的 gps 位置,调用第一个宏来完成工作并将每个最小距离附加到我的输出数据集。

/*** first concatenate your input lat, lon as well as some id into a | seperate long string for later %scan into individual input ***/

%macro min_distance;

data compute_all_dis;
set all_neighbor_gps_locations;
/** here create a new variable to this big dataset with the one point gps value***/
 first_lat = &latitude;
 first_lon = &longitude;
 ID = .
/** compute all **/
 distance = geodist(lat, long, first_lat, first_lon, 'dm');
run;

/** get the shorted distance***/
 proc sql;

 create table closest_neighbor as
 select milepost,OFF_PERIOD_ID, lat, long, first_lat, first_lon, distance 
 from compute_all_dis
    having distance = min ( distance);
quit;


%mend min_distance;



%macro find_all_closest_neighbors;

data _null_;
runno=countw("&ID",'|');
call symputx('runno',put(runno,8.));
run;

%put &runno;

    %do i=1 %to &runno;

    %let PERIOD = %SCAN(&OFF_ID, &i, "|");

    %let latitude = %SCAN (&LAT_I, &i, "|");
    %let longitude = %SCAN (&LONG_I, &i, "|");

    %min_distance;

    proc datasets nowarn;
    append base= pout.all_close_neighbors   data=closest_neighbor;
    run;

%end;
%mend find_all_closest_neighbors;
%find_all_closest_neighbors;