{"id":2074,"date":"2015-02-21T13:27:04","date_gmt":"2015-02-21T18:27:04","guid":{"rendered":"http:\/\/blogs.bu.edu\/ellisrp\/?p=2074"},"modified":"2015-07-23T11:00:33","modified_gmt":"2015-07-23T15:00:33","slug":"ellis-sas-tips-for-new-sas-programmers","status":"publish","type":"post","link":"https:\/\/blogs.bu.edu\/ellisrp\/2015\/02\/ellis-sas-tips-for-new-sas-programmers\/","title":{"rendered":"Ellis SAS tips for New SAS programmers"},"content":{"rendered":"<p>There is also a posting on <a href=\"http:\/\/blogs.bu.edu\/ellisrp\/2015\/02\/ellis-sas-tips-for-serious-sas-users\/\">Ellis SAS tips for Experienced SAS programmers<\/a><\/p>\n<p>It focuses on issues when using large datasets.<\/p>\n<p>&nbsp;<\/p>\n<p>Randy\u2019s SAS hints for New SAS programmers, updated Feb 21, 2015<\/p>\n<ol>\n<li>\n<h3><span style=\"color: #ff0000\"><strong><em><span style=\"text-decoration: underline\">ALWAYS<\/span><\/em><\/strong><\/span><\/h3>\n<p>begin and intermix your programs with internal documentation. (Note how I combined six forms of emphasis in ALWAYS: color, larger font, caps, bold, italics, underline.) Normally I recommend only one, but documenting your programs is <strong>really important. (Using only one form of emphasis is also important, just not really important.)<br \/>\n<\/strong><\/li>\n<\/ol>\n<p>A simple example to start your program in SAS is<\/p>\n<p>******************<br \/>\n* Program = test1, Randy Ellis, first version: March 8, 2013 \u2013 test program on sas features<br \/>\n***************;<\/p>\n<p>Any comment starting with an asterisk and ending in a semicolon is ignored;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"2\">\n<ol start=\"2\">\n<li><strong>Most common errors\/causes of wasted time while programming in SAS.<\/strong><\/li>\n<\/ol>\n<\/ol>\n<p>a. Forgetting semicolons at the end of a line<\/p>\n<p>b. Omitting a RUN statement, and then waiting for the program to run.<\/p>\n<p>c. Unbalanced single or double quotes.<\/p>\n<p>d. Unintentionally commenting out more code than you intend to.<\/p>\n<p>e. Foolishly running a long program on a large dataset that has not first been tested on a tiny one.<\/p>\n<p>f. Trying to print out a large dataset which will overflow memory or hard drive space.<\/p>\n<p>g. Creating an infinite loop in a datastep; Here is one silly one. Usually they can be much harder to identify.<\/p>\n<p>data infinite_loop;<br \/>\nx=1;<br \/>\nnevertrue=0;<br \/>\ndo while x=1;<br \/>\nif nevertrue =1 then x=0;<br \/>\nend;<br \/>\nrun;<\/p>\n<p>h. There are many other common errors and causes of wasted time. I am sure you will find your own<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"3\">\n<li><strong>With big datasets, 99 % of the time it pays to use the following system OPTIONS:<\/strong><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>options compress =yes nocenter;<\/p>\n<p>or<\/p>\n<p>options compress =binary nocenter;<\/p>\n<p>binary compression works particularly well with many binary dummy variables and sometimes is spectacular in saving 95%+ on storage space and hence speed.<\/p>\n<p>&nbsp;<\/p>\n<p>\/* mostly use *\/<br \/>\noptions nocenter \/* SAS sometimes spends many seconds figuring out how to center large print outs of<br \/>\ndata or results. *\/<br \/>\nps=9999 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/* avoid unneeded headers and page breaks that split up long tables in output *\/<br \/>\nls=200; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\/* some procs like PROC MEANS give less output if a narrow line size is used *\/<br \/>\n&nbsp;<\/p>\n<p>*other key options to consider;<\/p>\n<p>Options obs = max\u00a0\u00a0 \/* or obs=100, Max= no limit on maximum number of obs processed *\/<br \/>\nNodate nonumber \/* useful if you don\u2019t want SAS to embed headers at top of each page in listing *\/<br \/>\nMacrogen\u00a0\u00a0\u00a0\u00a0 \/* show the SAS code generated after running the Macros. *\/<br \/>\nMprint\u00a0\u00a0 \/* show how macro code and macro variables resolve *\/<br \/>\nnosource \/* suppress source code from long log *\/<br \/>\nnonotes\u00a0\u00a0 \/* be careful, but can be used to suppress notes from log for long macro loops *\/<\/p>\n<p>;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *remember to always end with a semicolon!;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"4\">\n<li><strong>Use these three key procedures regularly<\/strong><\/li>\n<\/ol>\n<p>Proc contents data=test; run; \/* shows a summary of the file similar to Stata\u2019s DESCRIBE *\/<br \/>\nProc means data = test (obs=100000); run; \/* set a max obs if you don\u2019t want this to take too long *\/<br \/>\nProc print data = test (obs=10); run;<\/p>\n<p>&nbsp;<\/p>\n<p>I recommend you create and use regularly a macro that does all three easily:<\/p>\n<p>%macro cmp(data=test);<br \/>\nProc Contents data=&amp;data; Proc means data = &amp;data (obs=1000); Proc print data = &amp;data (obs=10); run;<br \/>\n%end;<\/p>\n<p>Then do all three (<span style=\"text-decoration: underline\">c<\/span>ontents, <span style=\"text-decoration: underline\">m<\/span>eans, <span style=\"text-decoration: underline\">p<\/span>rint ten obs) with just<\/p>\n<p>%cmp(data = mydata);<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"5\">\n<li><strong>Understand temporary versus permanent files;<\/strong><\/li>\n<\/ol>\n<p>Data one;\u00a0\u00a0 creates a work.one temporary dataset that disappears when SAS terminates;<\/p>\n<p>Data out.one; creates a permanent dataset in the out directory that remains even if SAS terminates;<\/p>\n<p>&nbsp;<\/p>\n<p>Define libraries (or directories):<\/p>\n<p>Libname out \u201cc:\/data\/marketscan\/output\u201d;<br \/>\nLibname in \u201cc:\/data\/marketscan\/MSdata\u201d;<br \/>\n&nbsp;<\/p>\n<p>&nbsp;<\/p>\n<p>Output or data can be written into external files:<\/p>\n<p>Filename textdata \u201cc:\/data\/marketscan\/textdata.txt\u201d;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"6\">\n<li><strong>Run tests on small samples to develop programs and then Toogle between tiny and large samples when debugged.<\/strong><\/li>\n<\/ol>\n<p>A simple way is<\/p>\n<p>Options obs =10;<br \/>\n*options obs = max; *only use this when you are sure your programs run.<br \/>\n&nbsp;<\/p>\n<p>OR, some procedures and data steps using End= dataset option do not work well on partial samples. For those I often toggle between two different input libraries. Create a subset image of all of your data in a separate directory and then toggle using the libname commands;<\/p>\n<p>&nbsp;<\/p>\n<p>*Libname in \u2018c:\/data\/projectdata\/fulldata\u2019;<br \/>\nLibname in \u2018c:\/data\/projectdata\/testsample\u2019;<\/p>\n<p>&nbsp;<\/p>\n<p>Time spent creating a test data set is time well spent.<\/p>\n<p>You could even write a macro to make it easy. (I leave it as an exercise!)<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"7\">\n<li><strong>Use arrays abundantly. You can use different array names to reference the same set of variables. This is very convenient;<\/strong><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>%let rhs=x1 x2 y1 y2 count more;<br \/>\nData _null_;<br \/>\nArray X {100} X001-X100; *usual form;<br \/>\nArray y {100} ;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 * creates y1-y100;<br \/>\nArray xmat {10,10} X001-X100; *matrix notation allows two dimensional indexes;<br \/>\nArray XandY {*} X001-X100 y1-y100 index ; *useful when you don\u2019t know the count of variables in advance;<br \/>\nArray allvar &amp;rhs. ;\u00a0\u00a0\u00a0\u00a0 *implicit arrays can use implicit indexes;<br \/>\n&nbsp;<\/p>\n<p>*see various ways of initializing the array elements to zero;<\/p>\n<p>Do i = 1 to 100; x{i} = 0; end;<br \/>\n&nbsp;<\/p>\n<p>Do i = 1 to dim(XandY); XandY{i} = 0; end;<\/p>\n<p>&nbsp;<\/p>\n<p>Do over allvar; allvar = 0; end;\u00a0\u00a0 *sometimes this is very convenient;<\/p>\n<p>&nbsp;<\/p>\n<p>Do i=1 to 100 while (y(i) = . );<br \/>\ny{i} = 0;\u00a0\u00a0 *do while and do until are sometimes useful;<br \/>\nend;<\/p>\n<p>&nbsp;<\/p>\n<p>run;<\/p>\n<ol start=\"8\">\n<li><strong>For some purposes naming variables in arrays using leading zeros improves sort order of variables<\/strong><\/li>\n<\/ol>\n<p>Use:<br \/>\nArray x {100} X001-X100;<br \/>\nnot<br \/>\nArray x {100} X1-X100;<\/p>\n<p>With the second, the alphabetically sorted variables are x1,x10,x100, x11, x12,..,x19, x2,x20 , etc.<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"9\">\n<li><strong>Learn Set versus Merge command (Update is for rare, specialized use)<\/strong><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>Data three;\u00a0\u00a0 *information on the same person combined into a single record;<br \/>\nMerge ONE TWO;<br \/>\nBY IDNO;<br \/>\nRun;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"10\">\n<li><strong>Learn key dataset options like<\/strong><\/li>\n<\/ol>\n<p>Obs=<br \/>\nKeep=<br \/>\nDrop=<br \/>\nIn=<br \/>\nFirstobs=<br \/>\nRename=(oldname=newname)<br \/>\nEnd=<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"11\">\n<li><strong>Keep files being sorted \u201cskinny\u201d by using drop or keep statements<\/strong><\/li>\n<\/ol>\n<p>Proc sort data = IN.BIG(keep=IDNO STATE COUNTY FROMDATE) out=out.bigsorted;<br \/>\nBY STATE COUNTY IDNO FROMDATE;<br \/>\nRun;<\/p>\n<p>Also consider NODUP and NODUPKEY options to sort while dropping duplicate records, on all or on BY variables, respectively.<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"12\">\n<li><strong>Take advantage of BY group processing<\/strong><\/li>\n<\/ol>\n<p>Use FIRST.var and LAST.var abundantly.<\/p>\n<p>&nbsp;<\/p>\n<p>USE special variables<br \/>\n_N_ = current observation counter<br \/>\n_ALL_ set of all variables such as Put _all_. Or when used with PROC CONTENTS, set of all datasets.<\/p>\n<p>&nbsp;<\/p>\n<p>Also valuable is<\/p>\n<p>PROC CONTENTS data = in._all_; run;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"13\">\n<li><strong>Use lots of comments<\/strong><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n<p>* this is a standard SAS comment that ends with a semicolon;<\/p>\n<p>&nbsp;<\/p>\n<p>\/*\u00a0\u00a0 a PL1 style comment can comment out multiple lines including ordinary SAS comments;<\/p>\n<p>* Like this; *\/<\/p>\n<p>&nbsp;<\/p>\n<p>%macro junk; Macros can even comment out other macros or other pl1 style comments;<\/p>\n<p>\/*such as this; *\/ * O Boy!; %macro ignoreme;\u00a0\u00a0 mend; *very powerful;<\/p>\n<p>&nbsp;<\/p>\n<p>%mend; * end macro junk;<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"14\">\n<li><strong>Use meaningful file names!<\/strong><\/li>\n<\/ol>\n<p>Data ONE TWO THREE can be useful.<\/p>\n<p>&nbsp;<\/p>\n<ol start=\"15\">\n<li><strong>Put internal documentation about what the program does, who did it and when.<\/strong><\/li>\n<li><strong>Learn basic macro language;<\/strong> See SAS program demo for examples. Know the difference between <strong>executable<\/strong> and <strong>declarative <\/strong>statements used in DATA step<\/li>\n<\/ol>\n<p><strong>\u00a0<\/strong><\/p>\n<p><strong>17. EXECUTABLE COMMANDS USED IN DATA STEP (Actually DO something, once for every record)<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>Y=y+x (assignment. In STATA you would use GEN y=x or REPLACE Y=X)<br \/>\n&nbsp;<br \/>\nDo I = 1 to 10;<br \/>\nEnd; (always paired with DO, can be nested nearly unlimited deepness)<\/p>\n<p>&nbsp;<\/p>\n<p>INFile in \u2018c:\/data\/MSDATA\/claimsdata.txt\u2019;\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 define where input statements read from;<br \/>\nFile out \u2018c:\/data\/MSDATA\/mergeddata.txt\u2019;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 define where put statements write to;<\/p>\n<p><em>\u00a0<\/em><\/p>\n<p><em>Goto johnny; \u00a0\u00a0\u00a0\u00a0\u00a0* always avoid. Use do groups instead;<\/em><\/p>\n<p>&nbsp;<\/p>\n<p>IF a=b THEN y=0 ;<br \/>\nELSE y=x; * be careful when multiple if statements;<br \/>\nCALL <em>subroutine();<\/em> <em>(Subroutines are OK, Macros are better)<\/em><\/p>\n<p><em>\u00a0<\/em><\/p>\n<p>INPUT\u00a0\u00a0 X ; (read in one line of X as text data from INFILE)<br \/>\nPUT\u00a0\u00a0 x y= \/ z date.; (Write out results to current LOG or FILE file)<\/p>\n<p>&nbsp;<\/p>\n<p>MERGE IN.A IN.B ;<br \/>\nBY IDNO;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 *\u00a0\u00a0 Match up with BY variable IDNO as you simultaneously read in A&amp;B;<\/p>\n<p>Both files must already be sorted by IDNO.<\/p>\n<p>SET A B;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0* read in order, first all of A, and then all of B;<\/p>\n<p>UPDATE\u00a0\u00a0 A B; *replace variables with new values from B only if non missing in B;<\/p>\n<p>&nbsp;<\/p>\n<p>OUTPUT out.A;\u00a0\u00a0 \u00a0\u00a0\u00a0*Write out one obs to out.A SAS dataset;<br \/>\nOUTPUT; \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0*Writes out one obs of every output file being created;<\/p>\n<p>DELETE;\u00a0\u00a0 * do not output this record, and return to the top of the datastep;<\/p>\n<p>STOP;\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 * ends the current SAS datastep;<\/p>\n<p><strong>\u00a0<\/strong><\/p>\n<p><strong>18. Assignment commands for DATA Step are <\/strong><\/p>\n<p><strong>only done once at the start of the data step<\/strong><\/p>\n<p>&nbsp;<\/p>\n<p>DATA ONE TWO IN.THREE;<\/p>\n<p>*This would create three data sets, named ONE TWO and IN.THREE<\/p>\n<p>Only the third one will be kept once SAS terminates.;<\/p>\n<p>Array x {10} x01-x10;<br \/>\nATTRIB x length =16 Abc length=$8;<br \/>\nRETAIN COUNT 0;<br \/>\nBY state county IDNO;<br \/>\nAlso consider\u00a0\u00a0<br \/>\nBY DESCENDING IDNO; or BY IDNO UNSORTED; if grouped but not sorted by IDNO;<br \/>\nDROP i;\u00a0\u00a0 * do not keep i in final data set, although it can still be used while the data step is running<br \/>\nKEEP IDNO AGE SEX; *this will drop all variables from output file except these three;<br \/>\nFORMAT x date.;\u00a0\u00a0 *permanently link the format DATE. To the variable link;<\/p>\n<p>INFORMAT ABC $4.;<\/p>\n<p>LABEL AGE2010 = \u201cAge on December 31 2010\u201d;<br \/>\nLENGTH x 8; *must be assigned the first time you reference the variable;<br \/>\nRENAME AGE = AGE2010; After this point you must use the newname (AGE2010);<br \/>\nOPTIONS NOBS=100; One of many options. Note done only once.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>19. Key Systems language commands<\/strong><\/p>\n<p>LIBNAME to define libraries<br \/>\nFILENAME to define specific files, such as for text data to input or output text<\/p>\n<p>TITLE THIS TITLE WILL APPEAR ON ALL OUTPUT IN LISTING until a new title line is given;<\/p>\n<p>%INCLUDE<\/p>\n<p>%LET year=2011;<\/p>\n<p>%LET ABC = \u201cRandy Ellis\u201d;<\/p>\n<p>&nbsp;<\/p>\n<p><strong>20. Major procs you will want to master<\/strong><\/p>\n<p>DATA step !!!!! Counts as a procedure;<\/p>\n<p>PROC CONTENTS<\/p>\n<p>PROC PRINT<\/p>\n<p>PROC MEANS<\/p>\n<p>PROC SORT<\/p>\n<p>PROC FREQ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0frequencies<\/p>\n<p>PROC SUMMARY \u00a0\u00a0\u00a0\u00a0\u00a0(Can be done using MEANS, but easier)<\/p>\n<p>PROC CORR (Can be done using Means or Summary)<\/p>\n<p>PROC REG\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 OLS or GLS<\/p>\n<p>PROC GLM\u00a0\u00a0 General Linear Models with automatically created fixed effects<\/p>\n<p>PROC FORMAT \/INFORMAT<\/p>\n<p>PROC UNIVARIATE<\/p>\n<p>PROC GENMOD nonlinear models<\/p>\n<p>PROG SURVEYREG clustered errors<\/p>\n<p>None of the above will execute unless a new PROC is started OR you include a RUN; statement.<\/p>\n<p><strong>21. Formats are very powerful.<\/strong> Here is an example from the MarketScan data. One use is to simply recode variables so that richer labels are possible.<\/p>\n<p>&nbsp;<\/p>\n<p>Another use is to look up or merge on other information in large files.<\/p>\n<p>&nbsp;<\/p>\n<p>Proc format;<br \/>\nvalue $region<br \/>\n1=\u20191-Northeast Region\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n2=\u20192-North Central Region\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n3=\u20193-South Region\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n4=\u20194-West Region\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n5=\u20195-Unknown Region\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n;<\/p>\n<p>&nbsp;<\/p>\n<p>value $sex<\/p>\n<p>1=\u20181-Male\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\n2=\u20182-Female\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u2018<br \/>\nother=\u2018 Missing\/Unknown\u2019<\/p>\n<p>;<\/p>\n<p>&nbsp;<\/p>\n<p>*Three different uses of formats;<\/p>\n<p>Data one ;<br \/>\nsex=\u20191\u2019;<br \/>\nregion=1;<br \/>\nLabel sex = \u2018patient sex =1 if male\u2019;<br \/>\nlabel region = census region;<br \/>\nrun;<\/p>\n<p>Proc print data = one;<\/p>\n<p>Run;<\/p>\n<p>&nbsp;<\/p>\n<p>data two;<br \/>\nset one;<br \/>\n<strong>Format sex $sex.;<\/strong> * permanently assigns sex format to this variable and stores format with the dataset;<br \/>\nRun;<\/p>\n<p>Proc print data = two;<br \/>\nRun;<\/p>\n<p>Proc contents data = two;<br \/>\nRun;<\/p>\n<p>*be careful if the format is very long!;<\/p>\n<p>&nbsp;<\/p>\n<p>Data three;<br \/>\nSet one;<br \/>\n<strong>Charsex=put(sex,$sex.);<\/strong><br \/>\nRun;<\/p>\n<p>*maps sex into the label, and saves a new variable as the text strings. Be careful can be very long;<\/p>\n<p>Proc print data =three;<br \/>\nRun;<\/p>\n<p>&nbsp;<\/p>\n<p>Proc print data = one;<br \/>\n<strong>Format sex $sex.; <\/strong><br \/>\n*this is almost always the best way to use formats: Only on your results of procs, not saved as part of the datasets;<br \/>\nRun;<\/p>\n<p>&nbsp;<\/p>\n<p>If you are trying to learn SAS on your own, then I recommend you buy:<\/p>\n<div>\n<h2>The Little SAS Book: A Primer, Fifth Edition (or an earlier one)<\/h2>\n<p>Nov 7, 2012<\/p>\n<div>by Lora Delwiche and Susan Slaughter<\/div>\n<\/div>\n<p>Beginners introduction to SAS. Probably the best single book to buy when learning SAS.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>There is also a posting on Ellis SAS tips for Experienced SAS programmers It focuses on issues when using large datasets. &nbsp; Randy\u2019s SAS hints for New SAS programmers, updated Feb 21, 2015 ALWAYS begin and intermix your programs with internal documentation. (Note how I combined six forms of emphasis in ALWAYS: color, larger font, &hellip; <a href=\"https:\/\/blogs.bu.edu\/ellisrp\/2015\/02\/ellis-sas-tips-for-new-sas-programmers\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Ellis SAS tips for New SAS programmers<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2755,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[185,7238,10931,7241,7242,7243],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/posts\/2074"}],"collection":[{"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/users\/2755"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/comments?post=2074"}],"version-history":[{"count":4,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/posts\/2074\/revisions"}],"predecessor-version":[{"id":2193,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/posts\/2074\/revisions\/2193"}],"wp:attachment":[{"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/media?parent=2074"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/categories?post=2074"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.bu.edu\/ellisrp\/wp-json\/wp\/v2\/tags?post=2074"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}