/********************************** TOSA_CV ************************************/ /*This program is used to calculate centralized vector 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_CV(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 vector_&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; /*Calculate the inverse matrix of original covirance matrix*/ use cov; read all into cov; close cov; cov_inv=inv(cov); use &dat; read all into g; close &dat; use &dat._mean; read all into m; close &dat._mean; %do i=1 %to # /*Calculate the angle between any two vectors starting from the centroid*/ c1=g[&i,]; t_c1=t(c1); t_m=t(m); _tmp=c1*cov_inv*t_m; _r1=c1*cov_inv*t_c1; _r2=sqrt(_r1); _q1=m*cov_inv*t_m; _q2=sqrt(_q1); _rq=_r2*_q2; _rq_inv=inv(_rq); _z&i=_tmp*_rq_inv; create _z&i from _z&i[colname={"vector_&dat._mean"}]; append from _z&i; %end; quit; %do i=1 %to # /*Calculate the results*/ data vector_&dat._mean; set vector_&dat._mean _z&i;run; %end; proc datasets nolist; delete _z:; run; quit; %end; data test; merge vector_input_mean vector_output_mean; diff_sq=(vector_output_mean-vector_input_mean)**2; /*Calculate the suqare sum of the angle difference between input and output data*/ run; proc means data=test; var vector_output_mean vector_input_mean diff_sq; output out=means(drop=_TYPE_ _FREQ_); run; data means; set means; /*Calculate the mean difference*/ if _STAT_ in ('MEAN' 'N'); if _STAT_='N' then _STAT_='num_of_s'; if _STAT_='MEAN' then diff=sqrt(diff_sq); /*Calculate the result*/ run; proc export data= work.means /*Export the results*/ outfile= "&path.\TOSACV_result.xls" dbms=excel replace; sheet="TOSACV_result"; run; %mend; %TOSA_CV(sample=sample, data=input|output, path=C:\test);