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;
我有一个包含纬度、经度和海拔数据的点数据集。我想通过使用任意两个给定点(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;