/******************************* TOSA_CD **********************************/ /***This program is used to calculate centroid based topological change***/ /***********************Author: Nan "Wendy" Li ***************************/ /***********************wendyli0611@gmail.com*****************************/ /****************************May 16, 2015*********************************/ proc printto log="C:\temp\Save_my_log_please.log" new; /***Creat a log file***/ %macro TOSA_CD(sample,data); /*Input data*/ data _null_; call symputx('ndat',count("&data",'|')+1); run; %do k=1 %to &ndat; /*Read data from an Excel spreadsheet*/ %let dat=%scan(&data,&k,'|'); data dis_&dat._mean; set _null_; run; proc import out = &dat datafile = "&path.\&sample..xls" dbms = xls REPLACE; sheet = "&dat"; getnames = yes; run; proc contents data=&dat out=content;run; /*Read raw data into a SAS data table*/ proc sort data=content; by VARNUM;run; proc sql; select name into: vlist separated by ' ' from content; select count(name) into: nv from content; select distinct(NOBS) into: num from content; run; quit; %let num=%trim(%left(&num)); /*Initialize parameters*/ proc corr data=&dat cov out=cov; /*Calculate covirance matrix*/ var &vlist; run; data cov; set cov; /*Save covirance matrix*/ keep &vlist; if _n_ in (1:&nv); run; proc means data=&dat; output out=&dat._mean;run; /*Calculate the centroid of the raw data*/ data &dat._mean; set &dat._mean; drop _TYPE_ _FREQ_ _STAT_; if _n_=4; run; proc iml; use cov; read all into cov; close cov; cov_inv=inv(cov); /*Calculate the inverse matrix of original covirance matrix*/ use &dat; read all into g; close &dat; use &dat._mean; read all into m; close &dat._mean; %do i=1 %to # /*Calculate the mahalanobis distance between any data point and the centroid*/ c1=g[&i,]; c&i=c1-m; t_c&i=t(c&i); _tmp&i=c&i*cov_inv*t_c&i; _z&i=sqrt(_tmp&i); create _z&i from _z&i[colname={"dis_&dat._mean"}]; append from _z&i; %end; quit; %do i=1 %to # /*Calculate the results*/ data dis_&dat._mean; set dis_&dat._mean _z&i;run; %end; proc datasets nolist; delete _z:; run; quit; %end; data test; merge dis_input_mean dis_output_mean; /*Output the results into a data table*/ diff_sq=(dis_output_mean-dis_input_mean)**2; run; proc means data=test; /*Calculate the mean distance difference*/ var dis_output_mean dis_input_mean diff_sq; output out=means(drop=_TYPE_ _FREQ_); run; data means; set means; if _STAT_ in ('MEAN' 'N'); if _STAT_='N' then _STAT_='num_of_s'; if _STAT_='MEAN' then diff=sqrt(diff_sq); run; proc export data= work.means /*Export the results*/ outfile= "&path.\TOSACD_result.xls" dbms=excel replace; sheet="TOSACD_result"; run; %mend; %TOSA_CD(sample=sample, data=input|output, path=C:\test); proc printto; title; run;