Skip to content

Instantly share code, notes, and snippets.

@mnxoid
Last active August 30, 2019 15:14
Show Gist options
  • Save mnxoid/ddb84b5449c1ba6e971ed9dfe26bd5fc to your computer and use it in GitHub Desktop.
Save mnxoid/ddb84b5449c1ba6e971ed9dfe26bd5fc to your computer and use it in GitHub Desktop.
Useful tricks in SAS
data TEST;
format x date9.;
x = "11nov1996"d;
y = age(x, today());
z = age(x, addMonth(today(), 18));
run;
data tstd;
input n;
cards;
5
6
3
9
8
-5
-8
;
run;
proc ds2;
data TEST / overwrite=yes;
dcl double x having label 'Birthdate' format date9.;
dcl double y;
dcl double z;
dcl double tst;
method age(double birth, double dt) returns double;
return yrdif(birth, dt);
end;
method age(double birth) returns double;
return yrdif(birth, today());
end;
method addMonth(double dt, integer n) returns double;
return(intnx('month', dt, n));
end;
method run();
x = to_double(date '1996-11-11');
y = age(x);
z = age(x, addMonth(today(), 18));
set {select sum(n) as tst from tstd where n > 0};
end;
enddata;
run;
quit;
proc print data=TEST label;
run;
proc print data=tstd label;
run;
/************************ Other functions *******************************/
proc fcmp outlib = TEMP.FUNCTIONS.MAIN;
function test(a, b);
return(a + b*3);
endsub;
run;
/* To use these, paste the following code: */
option cmplib = TEMP.FUNCTIONS;
proc groovy;
submit parseonly;
class Speaker {
def say( word ) {
println "----> \"${word}\""
}
}
endsubmit;
quit;
proc groovy;
eval 's = new Speaker(); s.say( "Hi" )';
quit;
proc proto package = TEMP.USERFUNCS.NORM;
double normalize(double y, double mean, double var);
externc normalize;
double normalize(double y, double mean, double var)
{
double z;
int i;
z = (y - mean)/sqrt(var);
for (i=0;i<5;i=i+1) z = z+1;
return z;
}
externcend;
run;
proc fcmp inlib = TEMP.USERFUNCS outlib = TEMP.USERFUNCS.FUNCTIONS;
function sas_normalize(y,mean,var);
z = normalize(y,mean,var);
return(z);
endsub;
run;
options cmplib=TEMP.USERFUNCS;
data TEMP.temp;
y = 4;
z = sas_normalize(y,2,9);
run;
#define ON_EXCEPTION_GOTO(label) if (__fp_except) goto __fp_exception_##label;
#define EXCEPTION_LABEL(label) __fp_exception_##label :;
volatile int __fp_except;
#define TKTEXT(s) L##s
#define TKCHAR(s) L##s
#define ZMISS(dval) (((((int *)&dval)[1]) & 0xFFFF0000) == 0xFFFF0000)
extern void bktFPUSetup(void*);
/*----- stdlib protoypes -----*/
double sin(double);
double cos(double);
double tan(double);
double asin(double);
double acos(double);
double atan(double);
double atan2(double);
double sinh(double);
double cosh(double);
double tanh(double);
double exp(double);
double log(double);
double log2(double);
double log10(double);
double pow(double,double);
double sqrt(double);
double ceil(double);
double floor(double);
int abs(int);
double fabs(double);
double fmod(double,double);
int min(int,int);
int max(int,int);
double fmin(double,double);
double fmax(double,double);
char* efntkAlloc(char*,uint64_t);
#define malloc(len) efntkAlloc((char*)0x0000000000000000,len)
int32_t efntkRelease(char*,char*);
#define free(blob) efntkRelease((char*)0x0000000000000000,blob)
#define BL(to,len) __builtin_memset(to, ' ', len)
#define ML(from,to,len) __builtin_memcpy(to,from,len)
#define NULL ((void*)0)
/*----- tkext protoypes -----*/
struct TK_EXT_S
{
char TKGpad0[72];
};
typedef struct TK_EXT_S TKExtension;
typedef struct TK_EXT_S * TKExtensionh;
typedef void * TKPoolh;
typedef void * TkJnlh;
TKExtensionh tkExtensionLoad(char* name,int nameL);
void tksDestroy(TKExtensionh handle);
TkJnlh createTkJnl(void);
void destroyTkJnl(TkJnlh);
void tkJnlToLog(TkJnlh);
double normalize( double, double, double );
double normalize(double y, double mean, double var)
{
double z;
z = (y - mean)/sqrt(var);
for (int i=0;i<5;i=i+1) z = z+1;
return z;
}
/*====================
for (int i=0;i<5;i=i+1) z = z+1;
^^^
in-memory.c 73 Error 218: declaration found in statement block
Compilation User CPU Time: 0:00.0
Compilation System CPU Time: 0:00.0
Total memory allocated = 220912, High Amount in use = 220912
Generated Code and Data size = 0
******************* EXTERNC SOURCE END *********************
*/
/**********************************************************************************/
/* @file sums.sas */
/* @author mnxoid */
/* */
/* @macro sums - calculates row and column sums and adds them tho the table */
/**********************************************************************************/
/******************************************************************/
/* */
/* sums macro - calculates row and column sums and adds them */
/* to the table */
/* */
/* @param table - input table */
/* @param name_col - column with row labels */
/* @param out_table - output table */
/* @param row_total - row total column label */
/* @param col_total - column total row label */
/* @param columns - list of columns to calculate sums for */
/* */
/******************************************************************/
%macro sums(table, name_col, out_table, row_total, col_total, columns=_numeric_);
%let nodata = 0;/* At first we consider that the table is not empty */
/* Here we replace the missing values by zeros and count the number of columns */
data tidy;
set &table.;
array n &columns.;
_colcount_ = 0;
do over n;/* for each column */
if n=. then n=0; /* Replace missing with zero */
_colcount_ = _colcount_ + 1; /* Increment the number of columns */
end;
if _colcount_ = 0 then call symputx('nodata',1); /* If there are no columns, we have a problem */
drop _colcount_; /* Drop the temporary variable */
run;
%if &nodata. eq 1 %then %do; /* If there's no data */
%put WARNING: &table is empty. ; /* Print a warning */
data &out_table.;
set &table. end=eof;
&row_total.n = 0; /* Row total is zero for all */
output;
if eof then do; /* If last row */
&row_total.n = 0; /* Global total is zero */
&name_col. = &col_total.; /* Row label set to column total */
output;
end;
run;
%end;
%else %do; /* If we have some data to actually sum */
/* Here we calculate column sums */
proc means data=tidy noprint;
var &columns.;
output out=temp(drop=_type_ _freq_) sum=;
run;
/* Here we rename the resulting column into the desired label */
data temp;
set temp;
&name_col. = &col_total.;
run;
/* Here we concatenate the two tables, so we get the data and corresponding column totals */
data &out_table.;
set tidy temp;
array n {*} &columns.;
&row_total.n = sum(of n[*]); /* And also we calculate all row totals */
run;
/* Drop temporary tables */
proc sql;
drop table temp;
drop table tidy;
quit;
%end;
%mend;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment