<?xml version="1.0" encoding="utf-8"?>
  <rss version="2.0"
        xmlns:content="http://purl.org/rss/1.0/modules/content/"
        xmlns:atom="http://www.w3.org/2005/Atom"
  >
  <channel>
    <title></title>
    <link href="/feed/" rel="self" />
    <link href="http://yihui.name/" />
    <lastBuildDate>2016-08-02T13:13:57+00:00</lastBuildDate>
    <webMaster>xie@yihui.name</webMaster>
    
    <item>
      <title>SAS MapReduce: A Quick Followup by DS2</title>
      <link href="/2015/09/04/sas-mapreduce-a-quick-followup-by-ds2/"/>
      <pubDate>2015-09-04T14:01:30+00:00</pubDate>
      <author></author>
      <guid>/2015/09/04/sas-mapreduce-a-quick-followup-by-ds2</guid>
      <content:encoded><![CDATA[<font size="2">(</font>
<p><a href="https://support.sas.com/documentation/cdl/en/proc/67916/HTML/default/viewer.htm#n0ox2hnyx7twb2n13200g5hqqsmy.htm" target="_blank"><font size="2">DS2</font></a> <font size="2">would be the king!) Years ago I made up </font><a href="http://www.jiangtanghu.com/blog/2011/10/04/map-and-reduce-in-mapreduce-a-sas-illustration/" target="_blank"><font size="2">a piece of SAS code to demonstrate the basic idea of Map-Reduce</font></a><font size="2">. Now this idea can be best implemented by this piece of workable program with </font><a href="https://support.sas.com/documentation/cdl/en/proc/67916/HTML/default/viewer.htm#n0ox2hnyx7twb2n13200g5hqqsmy.htm" target="_blank"><font size="2">PROC DS2</font></a> <font size="2">(tested in SAS 9.4 TS1M2, Win7):</font></p>

<blockquote>
  <font size="2" face="Courier New">PROC DS2;</font>

  <font size="2" face="Courier New">/* create some data &#8211;*/ <br />data input_data / overwrite = yes; <br />dcl double d; <br />method init(); <br />&#160;&#160; dcl int i; <br />&#160;&#160; do i = 1 to 10000000; <br />&#160;&#160;&#160;&#160;&#160; /*&#8211; create some money values &#8211;*/ <br />&#160;&#160;&#160;&#160;&#160; d = round( (ranuni(123) * 10 ), .01 ); <br />&#160;&#160;&#160;&#160;&#160; output; <br />&#160;&#160; end; <br />end; <br />enddata; <br />run;</font>

  <font size="2" face="Courier New">/*&#8211; count the rows in multiple threads &#8211;*/ <br /><strong>thread</strong> <font color="#ff0000">map</font> / overwrite = yes; <br />dcl double c s; <br />keep c s; <br />method run(); <br />&#160;&#160; set input_data; <br />&#160;&#160; /*&#8211; the more compuation here, the more benefit &#8211;*/ <br />&#160;&#160; c + 1; <br />&#160;&#160; s + d; <br />end; <br />method term(); <br />&#160;&#160; output; <br />&#160;&#160; put s= c=; <br />end; <br />endthread; <br />run;</font>

  <font size="2" face="Courier New">/*&#8211; blend the results into one total &#8211;*/ <br />data <font color="#ff0000">reduce</font> / overwrite = yes; <br />dcl thread map m; <br />dcl double totc tots; <br />keep totc tots; <br />method run(); <br />&#160;&#160; set from m <font color="#ff0000">threads=4</font>; <br />&#160;&#160; totc + c; <br />&#160;&#160; tots + s; <br />end; <br />method term(); <br />&#160;&#160; output; <br />end; <br />enddata; <br />run; <br />quit;</font>

  <font size="2" face="Courier New">proc print data=reduce; run; <br /></font>
</blockquote>

<font size="2">Notice the option of “<font color="#ff0000">threads=4</font>”. You can specify the thread as any number you want (the number of slaves..).</font>

<font size="2">Thanks </font>
<p><a href="https://www.linkedin.com/pub/robert-ray/29/814/b73" target="_blank"><font size="2">Robert Ray</font></a> <font size="2">of SAS Institute to kindly allow me to post his code.</font></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>A Quick Look at SAS DS2 Merge</title>
      <link href="/2015/09/04/a-quick-look-at-sas-ds2-merge/"/>
      <pubDate>2015-09-04T12:02:39+00:00</pubDate>
      <author></author>
      <guid>/2015/09/04/a-quick-look-at-sas-ds2-merge</guid>
      <content:encoded><![CDATA[<font size="2">The code:</font>

<blockquote>
  <font size="2" face="Courier New">data a; <br />&#160;&#160;&#160; input i a $ b $; <br />&#160;&#160;&#160; datalines; <br />&#160;&#160;&#160; 1 a1A b1 <br />&#160;&#160;&#160; 1 a1A b1 <br />&#160;&#160;&#160; 2 a2 b2 <br />&#160;&#160;&#160; ; <br />run;</font>

  <font size="2" face="Courier New">data b; <br />&#160;&#160;&#160; input i a $ c $; <br />&#160;&#160;&#160; datalines; <br />&#160;&#160;&#160; 1 a1C c1 <br />&#160;&#160;&#160; 2 .&#160;&#160; c2 <br />&#160;&#160;&#160; 3 .&#160; c3 <br />&#160;&#160;&#160; ; <br />run;</font>

  <font size="2" face="Courier New">data mrge; <br />&#160;&#160;&#160; <font color="#ff0000">merge</font> a b; <br />&#160;&#160;&#160; by i; <br />run;</font>

  <font size="2" face="Courier New">proc ds2; <br />&#160;&#160;&#160; data ds2; <br />&#160;&#160;&#160;&#160;&#160;&#160; method run(); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <font color="#ff0000">merge</font> a b; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; by i; <br />&#160;&#160;&#160;&#160;&#160;&#160; end; <br />&#160;&#160;&#160;&#160; enddata; <br />&#160;&#160;&#160; run; <br />quit;</font>
</blockquote>

<font size="2">The outputs:</font>

<p><a href="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/09/SAS_DS2_merge.png"><font size="2"><img title="SAS_DS2_merge" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin: 3px auto 5px; display: block; padding-right: 0px; border-top-width: 0px" border="0" alt="SAS_DS2_merge" src="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/09/SAS_DS2_merge_thumb.png" width="307" height="480" /></font></a></p>

<font size="2">The comments:</font>

<font size="2">1. One of the weird behaviors of data step MERGE is that the value “c1” was carried over to row 2 of merged out dataset, Work.Mrge. In output dataset Work.Ds2 (generated by DS2), the row 2 of variable c is missing, which is kind of safe operation as we expected.</font>

<font size="2">2. In both output datasets, value ‘a1C’ overwrote ‘a1A’ in row 1.</font>

<font size="2">3. This DS2 MERGE is available in SAS 9.4 (TS1M3).</font>
]]></content:encoded>
    </item>
    
    <item>
      <title>SAS Combinatorial Functions: Snippets</title>
      <link href="/2015/06/25/sas-combinatorial-functions-snippets/"/>
      <pubDate>2015-06-25T12:55:38+00:00</pubDate>
      <author></author>
      <guid>/2015/06/25/sas-combinatorial-functions-snippets</guid>
      <content:encoded><![CDATA[<h3 id="permutation-and-combination">1. Permutation and Combination</h3>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">data <em>null</em>;<br /> n = 5;<br /> r = 2;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">   *the factorial of a number;<br /> fact=fact(n);</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">   *for positive integers, fact(n) = gamma(n+1);<br /> gamm=gamma(n + 1);</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">   *C(n,r): number of combinations of n objects selected r ;<br /> *n! / [r!(n-r)!];<br /> comb1 = comb(n,r);<br /> comb2 = fact(n) / (fact(r) * fact(n-r));<br /> comb3 = gamma(n+1) / (gamma(r+1) * gamma(n-r+1));<br /> comb4 = exp(lcomb(n,r));<br /> comb5 = exp(lgamma(n+1)-lgamma(r+1)-lgamma(n-r+1));</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">   *A(n,r): number of permutation (ordered arrangements);<br /> *n! / (n-r)!;<br /> perm1 = perm(n,r);<br /> perm2 = fact(n) /  fact(n-r);<br /> perm3 = gamma(n+1) /  gamma(n-r+1);<br /> perm4 = exp(lperm(n,r));<br /> perm5 = exp(lgamma(n+1)-lgamma(n-r+1));</span></p>

  <p><span style="font-size: xx-small;"><span style="font-family: 'Courier New';">   put (<em>all</em>) (= / );<br /> run;</span><br /> </span></p>
</blockquote>

<p><span style="font-size: xx-small;">Note functions <em>fact()</em> and <em>gamm()</em> can quickly reach out their limitations(<em>try n=<span style="color: #ff0000;">171 </span></em>and check the overflow notes in Log window).</span></p>

<h3 align="left">
  2. Generate Unique Pairs
</h3>

<p><span style="font-size: xx-small;">Question see </span><a href="http://stackoverflow.com/questions/19875633/how-to-pick-unique-pairs-from-a-single-list"><span style="font-size: xx-small;">here</span></a><span style="font-size: xx-small;">.</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">data <em>null</em>;<br /> array x[5] $1 (“A” “C” “D” “B” “E”);<br /> n = dim(x);<br /> r = 2;<br /> ncomb = comb(n, r);<br /> do j = 1 to ncomb+1;<br /> rc = <span style="color: #ff0000;">allcomb</span>(j, r, of x[*]);<br /> if rc &lt; 0 then leave;<br /> put j 5. +3 x1 “- ” x2 +3;<br /> end;<br /> run;</span></p>
</blockquote>

<p><span style="font-size: xx-small;">The output in Log:</span></p>

<blockquote>
  <p><span style="font-size: xx-small;">1   A – C<br /> 2   A – E<br /> 3   A – B<br /> 4   A – D<br /> 5   C – D<br /> 6   C – E<br /> 7   C – B<br /> 8   D – B<br /> 9   D – E<br /> 10   B – E</span></p>
</blockquote>

<p><span style="font-size: xx-small;">Or if you like alphabetical sorted pairs:</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">data <em>null</em>;<br /> array x[5] $1 (“A” “C” “D” “B” “E”);<br /> n = dim(x);<br /> r = 2;<br /> ncomb = comb(n, r);<br /> do j = 1 to ncomb+1;<br /> rc = <span style="color: #ff0000;">lexcomb</span>(j, r, of x[*]);<br /> if rc &lt; 0 then leave;<br /> put j 5. +3 x1 “- ” x2 +3;<br /> end;<br /> run;</span></p>
</blockquote>

<p><span style="font-size: xx-small;">The output:</span></p>

<blockquote>
  <p><span style="font-size: xx-small;">1   A – B<br /> 2   A – C<br /> 3   A – D<br /> 4   A – E<br /> 5   B – C<br /> 6   B – D<br /> 7   B – E<br /> 8   C – D<br /> 9   C – E<br /> 10   D – E</span></p>
</blockquote>

<p><span style="font-size: xx-small;">I checked </span><a href="http://blogs.sas.com/content/iml/"><span style="font-size: xx-small;">Rick Wicklin’s blog</span></a> <span style="font-size: xx-small;">and found  </span><a href="http://blogs.sas.com/content/iml/2013/09/30/generate-combinations-in-sas.html"><span style="font-size: xx-small;">PROC IML</span></a> <span style="font-size: xx-small;">offers a much more intuitive approach to this problem:</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">proc iml;<br /> n = 5;<br /> r = 2;<br /> idx = <span style="color: #ff0000;">allcomb</span>(n, r);<br /> print idx;<br /> quit;</span></p>
</blockquote>

<p><span style="font-size: xx-small;">The output:</span></p>

<blockquote>
  <p><span style="font-size: xx-small;">1 2<br /> 2 3<br /> 1 3<br /> 3 4<br /> 2 4<br /> 1 4<br /> 4 5<br /> 3 5<br /> 2 5<br /> 1 5 </span></p>
</blockquote>

<p><span style="font-size: xx-small;">or make the output more readable:</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">proc iml;<br /> n = 5;<br /> r = 2;<br /> idx = allcomb(n, r);<br /> print idx;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">    Items = {“A” “C” “D” “B” “E”};<br /> S = Items[ ,idx];<br /> S = shape(S, 0, r);<br /> print S[r=(char(1:nrow(S)))];<br /> quit;</span></p>
</blockquote>

<p><span style="font-size: xx-small;">the output:</span></p>

<blockquote>
  <p><span style="font-size: xx-small;">1  A C<br /> 2  C D<br /> 3  A D<br /> 4  D B<br /> 5  C B<br /> 6  A B<br /> 7  B E<br /> 8  D E<br /> 9  C E<br /> 10 A E </span></p>
</blockquote>

<h3 id="generate-unique-pairs-a-macro">3. Generate Unique Pairs: A Macro</h3>

<p><span style="font-size: xx-small;">Years ago when the build-in functions above might not be available in SAS, a </span><a href="http://www.urz.uni-heidelberg.de/statistik/sas/doc/ts498-combperm.txt"><span style="font-size: xx-small;">macro %combo</span></a> <span style="font-size: xx-small;">did the same job:</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">%combo(2,a,c,d,b,e)</span></p>
</blockquote>

<p><span style="font-size: xx-small;">The output:</span></p>

<blockquote>
  <p><span style="font-size: xx-small;">1  a c<br /> 2  a d<br /> 3  a b<br /> 4  a e<br /> 5  c d<br /> 6  c b<br /> 7  c e<br /> 8  d b<br /> 9  d e<br /> 10 b e<br /> </span></p>
</blockquote>

<p><span style="font-size: xx-small;">It’s fun to check out the macro how to implement it by arrays.</span></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Statistical Notes (3B): Confidence Intervals for Binomial Proportion Using SAS, Updated</title>
      <link href="/2015/05/22/statistical-notes-3b-confidence-intervals-for-binomial-proportion-using-sas-updated/"/>
      <pubDate>2015-05-22T22:05:39+00:00</pubDate>
      <author></author>
      <guid>/2015/05/22/statistical-notes-3b-confidence-intervals-for-binomial-proportion-using-sas-updated</guid>
      <content:encoded><![CDATA[<font size="1">This quick note serves as a supplementnote of my previous </font>
<p><a href="http://www.jiangtanghu.com/blog/2012/09/15/confidence-intervals-binomial-proportion/"><font size="1">Statistical Notes (3): Confidence Intervals for Binomial Proportion Using SAS</font></a> <font size="1">which I will extend as a </font><a href="http://www.sesug.org/SESUG2015/index.php"><font size="1">SESUG 2015</font></a> <font size="1">paper. Basically I added a new Blaker method to my <em><a href="https://raw.githubusercontent.com/Jiangtang/Programming-SAS/master/CI_Single_Proportion.sas">CI_Single_Proportion.sas</a></em> file and found more CIs from SAS PROC FREQ.</font></p>

<font size="1">First of all, call the script:</font>

<blockquote>
  <font size="1"><font face="Courier New">filename CI url “</font><font face="Courier New"><a href="https://raw.github.com/Jiangtang/Programming-SAS/master/CI_Single_Proportion.sas">https://raw.github.com/Jiangtang/Programming-SAS/master/CI_Single_Proportion.sas</a>” ;</font> <br /><font face="Courier New">%include CI;</font></font>

  <font size="1" face="Courier New">%CI_Single_Proportion(r=81,n=263);</font>
</blockquote>

<font size="1">and the output:</font>

<p><a href="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/CI_SAS.png"><img title="CI_SAS" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin: 3px auto 5px; display: block; padding-right: 0px; border-top-width: 0px" border="0" alt="CI_SAS" src="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/CI_SAS_thumb.png" width="493" height="306" /></a></p>

<font size="1">The #12 is the one newly added. We can get the same results by SAS PROC FREQ (I use SAS/Base 9.4, TS1M2, WIN64):</font>

<blockquote>
  <font size="1" face="Courier New">data test; <br />input grp outcome $ count; <br />datalines; <br />1 f 81 <br />1 u 182 <br />;</font>

  <font size="1" face="Courier New">ods select BinomialCLs; <br />proc freq data=test; <br />&#160;&#160;&#160; tables outcome / binomial (CL= <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WALD <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WILSON <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; CLOPPERPEARSON <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; MIDP <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LIKELIHOODRATIO <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; JEFFREYS <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; AGRESTICOULL <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LOGIT <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; BLAKER&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ); <br />&#160;&#160;&#160; weight Count; <br />run;</font>

  <font size="1" face="Courier New">ods select BinomialCLs; <br />proc freq data=test; <br />&#160;&#160;&#160; tables outcome / binomial (CL = <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WILSON(CORRECT) <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; WALD(CORRECT) <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ); <br />&#160;&#160;&#160; weight Count; <br />run;</font>
</blockquote>

<font size="1" face="Courier New">the output:</font>

<p><a href="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/CI_SAS_FREQ.png"><img title="CI_SAS_FREQ" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin: 3px auto 5px; display: block; padding-right: 0px; border-top-width: 0px" border="0" alt="CI_SAS_FREQ" src="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/CI_SAS_FREQ_thumb.png" width="314" height="480" /></a></p>

<font size="1">Only #10 method is not implemented yet in SAS PROC FREQ. There are some Bayesian intervals available in SAS&#160; procedures but since I’m not familiar with Bayes, I will leave it blank by far.</font>
]]></content:encoded>
    </item>
    
    <item>
      <title>Calculating Covariance by SAS, A Brutal Way</title>
      <link href="/2015/05/12/calculating-covariance-by-sas-a-brutal-way/"/>
      <pubDate>2015-05-12T15:56:16+00:00</pubDate>
      <author></author>
      <guid>/2015/05/12/calculating-covariance-by-sas-a-brutal-way</guid>
      <content:encoded><![CDATA[<p><span style="font-size: xx-small">It was very disappointed that there is only one built-in method to calculate covariance in Base SAS: that’s in </span><a href="http://support.sas.com/documentation/cdl/en/proc/67327/HTML/default/viewer.htm#p0v0y1on1hbxukn0zqgsp5ky8hc0.htm"><span style="font-size: xx-small">PROC CORR</span></a> <span style="font-size: xx-small">(while you can also do it in </span><a href="http://blogs.sas.com/content/iml/2010/12/08/computing-covariance-and-correlation-matrices.html"><span style="font-size: xx-small">SAS/IML</span></a><span style="font-size: xx-small">, of course):</span></p>

<p><a href="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/sascorr.png"><span style="font-size: xx-small"><img title="sascorr" style="border-left-width: 0px; border-right-width: 0px; background-image: none; border-bottom-width: 0px; float: none; padding-top: 0px; padding-left: 0px; margin: 3px auto 5px; display: block; padding-right: 0px; border-top-width: 0px" border="0" alt="sascorr" src="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/sascorr_thumb.png" width="443" height="249" /></span></a></p>

<p><span style="font-size: xx-small">The following is a quick-and-dirty way to get a function like %COV:</span></p>

<blockquote>
  <font face="Courier New">%macro COV(data, var1,var2); <br />&#160;&#160;&#160; %local _cov; <br />&#160;&#160;&#160; %let rc = %sysfunc(dosubl(%str(</font>

  <font face="Courier New">&#160;&#160;&#160; ods select none ; <br />&#160;&#160;&#160; ods output cov=_cov;</font>

  <font face="Courier New">&#160;&#160;&#160; proc corr data=&amp;data&#160; cov ; <br />&#160;&#160;&#160; var &amp;var1 &amp;var2 ; <br />&#160;&#160;&#160; run;</font>

  <font face="Courier New">&#160;&#160;&#160; ods select all;</font>

  <font face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; proc sql noprint; <br />&#160;&#160;&#160; select &amp;var2 into :_cov <br />&#160;&#160;&#160; from _cov&#160; (obs=1) <br />&#160;&#160;&#160; ; <br />&#160;&#160;&#160; drop table&#160; _cov; <br />&#160;&#160;&#160; quit <br />&#160;&#160;&#160; ))); <br />&#160;&#160;&#160; &amp;_cov <br />%mend COV;</font>

  <p><span style="font-size: xx-small; font-family: &#39;Courier New&#39;"></span></p>
</blockquote>

<p><span style="font-size: xx-small">You can use it in macro variable assignment:</span></p>

<blockquote>
  <p><span style="font-size: xx-small; font-family: &#39;Courier New&#39;">%let cov = %COV(sashelp.iris,SepalLength,SepalWidth);</span></p>
</blockquote>

<p><span style="font-size: xx-small">or in a data step:</span></p>

<blockquote>
  <p><span style="font-size: xx-small; font-family: &#39;Courier New&#39;">data iris; <br />    set sashelp.iris; <br />    cov = %COV(sashelp.iris,SepalLength,SepalWidth); <br />run;</span></p>
</blockquote>

<p><span style="font-size: xx-small">or in PROC SQL:</span></p>

<blockquote>
  <p><span style="font-size: xx-small; font-family: &#39;Courier New&#39;">proc sql; <br />    create table iris2 as <br />    select *, <br />    %COV(sashelp.iris,SepalLength,SepalWidth) as cov <br />    from sashelp.iris; <br />quit;</span></p>
</blockquote>

<p><span style="font-size: xx-small">One line conclusion: I LOVE </span><a href="http://www.jiangtanghu.com/blog/2015/03/09/list-manipulations-made-easy-and-little-bit-of-ugly-the-new-dosubl-function/"><span style="font-size: xx-small">Dosubl</span></a> and hope this Dosubl also inspires your programming<span style="font-size: xx-small">!</span></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Import .Rdata to SAS, along with Labels</title>
      <link href="/2015/05/12/import-rdata-to-sas-along-with-labels/"/>
      <pubDate>2015-05-12T13:06:28+00:00</pubDate>
      <author></author>
      <guid>/2015/05/12/import-rdata-to-sas-along-with-labels</guid>
      <content:encoded><![CDATA[<p><span style="font-size: xx-small;">I didn’t </span><a href="http://www.jiangtanghu.com/blog/2010/10/29/sas-iml-basic/"><span style="font-size: xx-small;">play with SAS/IML</span></a> <span style="font-size: xx-small;">for a while. I call it back when I need to read some R format data.</span></p>

<p><span style="font-size: xx-small;">Technically, .Rdata is not a data format. It’s rather a big container to hold bunch of R objects:</span></p>

<p><span style="font-size: xx-small;"><a href="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/Rdata1.png"><img style="background-image: none; float: none; padding-top: 0px; padding-left: 0px; margin: 3px auto 5px; display: block; padding-right: 0px; border: 0px;" title="Rdata" src="http://www.jiangtanghu.com/blog/wp-content/uploads/2015/05/Rdata_thumb1.png" alt="Rdata" width="408" height="213" border="0" /></a></span></p>

<p><span style="font-size: xx-small;">In this example, when a .Rdata is loaded, 3 objects are included where ‘data’(the ‘real’ data) and ‘desc’ (data description portion) are of our interests.</span></p>

<p><span style="font-size: xx-small;">SAS/IML offers a nice interface to call R command which can be used to read the R format data:</span></p>

<blockquote>
  <p><span style="font-family: 'Courier New'; font-size: xx-small;">proc iml;<br /> <strong>submit / R;</strong><br /> load(“C:/data/w5/R data sets for 5e/GPA1.RData”)<br /> <strong>endsubmit;</strong></span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">    <strong>call</strong> <strong>ImportDataSetFromR</strong>(“work.GPA1”, “<span style="color: #ff0000;">data</span>“);<br /> <strong>call</strong> <strong>ImportDataSetFromR</strong>(“work.GPA1desc”, “<span style="color: #ff0000;">desc</span>“);</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">quit;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">data <em>null</em>;<br /> set GPA1desc end = eof ;<br /> i+1;<br /> II=left(put(i,3.));<br /> call symputx(‘var’||II,variable);<br /> call symputx(‘label’||II,label);<br /> if eof then call symputx(‘n’,II);<br /> run;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">%macro labelit;<br /> data gpa1;<br /> set gpa1;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">    label<br /> %do i=1 %to &amp;n;<br /> &amp;&amp;var&amp;i = &amp;&amp;label&amp;i<br /> %end;<br /> ;<br /> run;<br /> %mend;</span></p>

  <p><span style="font-family: 'Courier New'; font-size: xx-small;">%labelit</span></p>
</blockquote>
]]></content:encoded>
    </item>
    
    <item>
      <title>Confidence Intervals for Binomial Proportion (Again): A Quick Note</title>
      <link href="/2015/05/05/ci-mcmc/"/>
      <pubDate>2015-05-05T14:22:33+00:00</pubDate>
      <author></author>
      <guid>/2015/05/05/ci-mcmc</guid>
      <content:encoded><![CDATA[<p>In <a href="http://lexjansen.com/">Lex</a>’s library of the latest SAS Global Forum 2015 papers, I found an interesting paper by Wu Gong, <em><a href="http://support.sas.com/resources/papers/proceedings15/3020-2015.pdf">Jeffreys Interval for One-Sample Proportion with SAS/STAT Software</a></em>, where SAS MCMC procedure and a so called Random Walk Metropolis Algorithm were implemented to calculate the Jeffreys interval for binomial proportion.</p>

<p>Years ago I wrote several posts on this topic:</p>

<blockquote>
  <p><a href="http://www.jiangtanghu.com/blog/2012/09/15/confidence-intervals-binomial-proportion/">Statistical Notes (3): Confidence Intervals for Binomial Proportion Using SAS</a></p>

  <p><a href="http://www.jiangtanghu.com/blog/2012/09/23/statistical-notes-5-confidence-intervals-for-difference-between-independent-binomial-proportions-using-sas/">Statistical Notes (5): Confidence Intervals for Difference Between Independent Binomial Proportions Using SAS</a></p>

  <p><a href="http://www.jiangtanghu.com/blog/2013/08/22/confidence-intervals-for-binomial-proportion-a-sas-9-4stat-12-3-update/">Confidence Intervals for Binomial Proportion: A SAS 9.4/STAT 12.3 Update</a></p>

  <p><a href="http://www.jiangtanghu.com/blog/2013/08/25/confidence-intervals-for-difference-between-independent-binomial-proportions-a-sas-9-4stat-12-3-update/">Confidence Intervals for Difference Between Independent Binomial Proportions: A SAS 9.4/STAT 12.3 Update</a></p>
</blockquote>

<p>I’m not a statistician and I might get some time later to dig these new methods in Wu’s paper (I modified his codes little bit to fit my post):</p>

<blockquote>
  <font face="Courier New">/*0 input data*/ <br />data jeff; <br />&#160;&#160;&#160; n=263; <br />&#160;&#160;&#160; r=81; <br />run;</font>

  <font face="Courier New">/*1 Random Walk Metropolis*/ <br />%let nmc=1010000; <br />%let c=0.08;</font>

  <font face="Courier New">data PosteriorSample; <br />&#160;&#160;&#160; call streaminit(123); <br />&#160;&#160;&#160; set jeff; <br />&#160;&#160;&#160; p0=0.5; <br />&#160;&#160;&#160; retain p0;</font>

  <font face="Courier New">&#160;&#160;&#160; do i = 1 to &nmc.; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; p1=p0+rand(&#8216;normal&#8217;,0,&amp;c.); </font>

  <font face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; do while(p1 lt 0 or p1 gt 1); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p1=p0+rand(&#8216;normal&#8217;,0,&amp;c.); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; end;</font>

  <font face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; logratio=(1/2-1)*log(p1)+(1/2-1)*log(1-p1)+r*log(p1)+(n-r)*log(1-p1) <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8211; (1/2-1)*log(p0)-(1/2-1)*log(1-p0)-r*log(p0)-(n-r)*log(1-p0); </font>

  <font face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if log(rand(&#8216;uniform&#8217;)) &lt;= logratio then do; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; p0=p1; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; end;</font>

  <font face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; if i gt 10000 and floor(i/20)*20 eq i then do; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; output; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; end; <br />&#160;&#160;&#160; end; <br />&#160;&#160;&#160; keep i p0; <br />run;</font>

  <font face="Courier New">title "Jeffreys Interval by Random Walk Metropolis Algorithm"; <br />proc univariate data=PosteriorSample noprint; <br />&#160;&#160;&#160; var p0; <br />&#160;&#160;&#160; output out=PP pctlpts = 2.5 97.5 pctlpre = pct; <br />run;</font>

  <font face="Courier New">proc print data=pp noobs; <br />&#160;&#160;&#160; format pct2_5 pct97_5 6.4; <br />run; <br />title;</font>

  <font face="Courier New">/*2 MCMC*/ <br />title "Jeffreys Credible Interval by PROC MCMC"; <br />ods select PostIntervals; <br />proc mcmc data=jeff <br />&#160;&#160;&#160; seed=123 <br />&#160;&#160;&#160; outpost=PosteriorSample2 <br />&#160;&#160;&#160; nbi=10000 <br />&#160;&#160;&#160; nthin=20 <br />&#160;&#160;&#160; nmc=1000000 <br />&#160;&#160;&#160; statistics=(summary interval) diagnostics=none plots=none; <br />&#160;&#160;&#160; parms prb 0.5; <br />&#160;&#160;&#160; prior prb ~ beta(1/2,1/2); <br />&#160;&#160;&#160; model r ~ binomial(n,prb); <br />run; <br />title;</font>
</blockquote>
]]></content:encoded>
    </item>
    
    <item>
      <title>List Manipulations Made Easy (and little bit of UGLY): the New DOSUBL Function</title>
      <link href="/2015/03/09/list-manipulations-made-easy-and-little-bit-of-ugly-the-new-dosubl-function/"/>
      <pubDate>2015-03-09T15:07:54+00:00</pubDate>
      <author></author>
      <guid>/2015/03/09/list-manipulations-made-easy-and-little-bit-of-ugly-the-new-dosubl-function</guid>
      <content:encoded><![CDATA[<font size="1">Typically, </font>
<p><a href="http://www.jiangtanghu.com/blog/2013/03/31/list-processing-with-sas-a-github-repository/"><font size="1">SAS list manipulations</font></a> <font size="1">needs bunch of SAS I/O functions which are not necessarily well known to all SAS programmers. The new </font><a href="http://support.sas.com/documentation/cdl/en/lefunctionsref/67398/HTML/default/viewer.htm#p09dcftd1xxg1kn1brnjyc0q93yk.htm"><font size="1">DOSUBL</font></a> <font size="1">function makes this technique much more easier and little bit of ugly I must admit:</font></p>

<blockquote>
  <font size="1" face="Courier New">%MACRO ExpandVarList(data=_LAST_, var=_ALL_); <br />&#160;&#160;&#160; %if %upcase(%superq(data)) = _LAST_ <br />&#160;&#160;&#160; %then %let data = &SYSLAST; <br />&#160;&#160;&#160; %let rc = %sysfunc(dosubl(%str( <br />&#160;&#160;&#160; proc transpose data=&amp;DATA(obs=0) out=ExpandVarList_temp; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; var &VAR; <br />&#160;&#160;&#160; run; <br />&#160;&#160;&#160; proc sql noprint; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; select _name_ into :temp_varnames separated by &#8216; &#8216; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; from ExpandVarList_temp <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ; <br />&#160;&#160;&#160; drop table ExpandVarList_temp; <br />&#160;&#160;&#160; quit <br />&#160;&#160;&#160; ))); <br />&#160;&#160;&#160; &amp;temp_varnames <br />%MEND ExpandVarList;</font>

  <font size="1" face="Courier New">%put %ExpandVarList(data=sashelp.class);</font>
</blockquote>

<font size="1">This piece of code comes from <em><a href="https://support.sas.com/resources/papers/proceedings13/032-2013.pdf">Submitting SAS Code On The Side</a></em> by Rick Langston. It’s not elegant by any means compared to </font>
<p><a href="https://github.com/Jiangtang/SAS_ListProcessing/blob/master/getVar.sas"><font size="1">this version</font></a><font size="1">, but does have huge advantage of utilizing traditional SAS programming elements like data steps, procedures and such.</font></p>

<font size="1">&#8212;&#8212;&#8212;&#8212;UPDATE 2015-03-16&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;</font>

<font size="1">Ronan Martorell, a SAS programmer from Paris, came out other two methods for the task above, also leveraged by DOSUBL (<em>the sky is not limited!</em>). The followings are his piece of codes (with permissions; Thank you Ronan!):</font>

<blockquote>
  <font size="1">&#160;<font face="Courier New">/* <font color="#ff0000">&#8212; Method no. 2 :using a Data Step + Array launched by DOSUBL&#8211;</font> */ <br />%macro VarList(data=); <br />&#160;&#160;&#160; %local varlist;</font></font>

  <font size="1" face="Courier New">&#160;&#160;&#160; /* DOSUBL required for executing the Data Step in a distinct session */ <br />&#160;&#160;&#160; %let rc = %sysfunc(dosubl(%str( <br />&#160;&#160;&#160; Data _null_; <br />&#160;&#160;&#160; length varlist $32167.; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; set &amp;data(obs=1); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; array avarn[*] _NUMERIC_; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; array avarc[*] _CHARACTER_; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; do i=1 to dim(avarn); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; varlist=CATX(&#8216; &#8216;,varlist, vname(avarn[i])); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; end; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; do i=1 to dim(avarc); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; *no self-reference allowed!; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if vname(avarc[i]) NE &#8216;varlist&#8217; then <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; varlist=CATX(&#8216; &#8216;,varlist, vname(avarc[i])); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; end; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; call symputx(&#8216;varlist&#8217;,varlist); <br />&#160;&#160;&#160; run; <br />&#160;&#160;&#160; ))); <br />&#160;&#160;&#160; <br />&#160;&#160;&#160; &amp;varlist <br />%mend VarList; <br />%put %VarList(data=sashelp.class);</font>

  <font size="1" face="Courier New">/* <font color="#ff0000">&#8212; Method no. 3:&#160; using Dictionary View COLUMNS launched by DOSUBL</font> &#8211;*/ <br />%macro VarlistDIC(data=); <br />&#160;&#160;&#160; %local libname memname varlist;</font>

  <font size="1" face="Courier New">&#160;&#160;&#160; /* Test : if . separator exists in DataSet name then extracts Libname &amp; Memname strings accordingly */ <br />&#160;&#160;&#160; %let libname=%UPCASE( %sysfunc( IFC( %index(&amp;data, .) EQ 0, WORK, %scan(&amp;data, <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; 1) ))); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; %let memname=%UPCASE( %sysfunc( IFC( %index(&amp;data, .) EQ 0, &amp;data, <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; %scan(&amp;data, 2) ))); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; %let rc = %sysfunc(dosubl(%str( </font>

  <font size="1" face="Courier New">&#160;&#160;&#160; proc sql noprint; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; select name into :varlist separated by &#8216; &#8216; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; from DICTIONARY.COLUMNS <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; where libname EQ "&amp;libname" and memname EQ "&amp;memname" <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; ; <br />&#160;&#160;&#160; quit; <br />&#160;&#160;&#160; )));</font>

  <font size="1" face="Courier New">&#160;&#160;&#160; &amp;varlist <br />%mend VarlistDIC; <br />%put %VarListDIC(data=sashelp.class);</font>
</blockquote>

<font size="1">Ronan also kindly contributed his I/O version (check out <a href="https://github.com/Jiangtang/SAS_ListProcessing/blob/master/getVar.sas">another I/O version in my github page</a>):</font>

<blockquote>
  <font size="1" face="Courier New">/* <font color="#ff0000">&#8212; Method no. 4 : using SCL function with iterative FETCHOB + DICTIONARY VIEW &#8212;</font> */ <br />%macro ListVar(libname=, memname=); <br />&#160;&#160;&#160; /* local var initialisation */ <br />&#160;&#160;&#160; %let listvar=; <br />&#160;&#160;&#160; %let i=0;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160; /* open dictionary view with WHERE clause*/ <br />&#160;&#160;&#160; %let id=%sysfunc(open(sashelp.vcolumn (where=( libname = "%upcase(&amp;libname)" AND memname= "%upcase(&amp;memname)")))); <br />&#160;&#160;&#160; /* load variable names into macro-variables (beware macro var collision !) */ <br />&#160;&#160;&#160; /* Cf. </font>
  <p><a href="http://www.notecolon.info/2013/01/note-open-function-reading-data-sets-in.html"><font size="1" face="Courier New">http://www.notecolon.info/2013/01/note-open-function-reading-data-sets-in.html</font></a> <font size="1" face="Courier New">*/ <br />&#160;&#160;&#160; %syscall set(id); <br />&#160;&#160;&#160; %let rc=0; <br />&#160;&#160;&#160; /* loop into each line and accumulate the variable names into a list*/ <br />&#160;&#160;&#160; %do %until(&amp;rc LT 0); <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %let i=&amp;i+1; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %let rc=%sysfunc(fetchobs(&amp;id, &amp;i));</font></p>

  <font size="1" face="Courier New">&#160;&#160;&#160;&#160;&#160;&#160;&#160; /* force loop exit once last variable has been stored into the list */ <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %let listvar= %sysfunc( IFC ( &amp;rc GE 0, &amp;listvar &amp;Name, &amp;listvar )); <br />&#160;&#160;&#160; %end; <br />&#160;&#160;&#160; %let id=%sysfunc(close(&amp;id));</font>

  <font size="1" face="Courier New">&#160;&#160; /* expands the list */ <br />&#160; &amp;listvar <br />%mend; <br />%put %ListVar(libname=sashelp, memname=class);</font>
</blockquote>
]]></content:encoded>
    </item>
    
    <item>
      <title>Takeaway Materials From PharmaSUG SDE, Cary, NC</title>
      <link href="/2014/09/29/takeaway-materials-from-pharmasug-sde-cary-nc/"/>
      <pubDate>2014-09-29T21:59:02+00:00</pubDate>
      <author></author>
      <guid>/2014/09/29/takeaway-materials-from-pharmasug-sde-cary-nc</guid>
      <content:encoded><![CDATA[<p>It’s the first <a href="http://www.pharmasug.org/sde/cary2014.html" target="_blank">PharmaSUG event</a> I ever attended and it’s great and I plan to submit a paper for PharmaSUG 2015.</p>

<p>Honors belonged to Mike Molter and Lex Jansen for their hardcore talks on XML and CDISC Dataset-XML respectively. <a href="http://www.cdisc.org/dataset-xml" target="_blank">Dataset-XML</a> is basically ODM based replacement of currently wildly used <a href="http://support.sas.com/kb/46/944.html" target="_blank">SAS Version 5 Transport File</a>. It’s an emerging technology and it’s nice to check it out:</p>

<blockquote>
  <p><a href="http://wiki.cdisc.org/display/PUB/CDISC+Dataset-XML+Resources" target="_blank">CDISC Dataset-XML Resources @CDISC</a></p>

  <p><a href="http://support.sas.com/rnd/base/cdisc/cst/#preprod" target="_blank">Support for Dataset-XML v1.0 @SAS</a></p>
</blockquote>
]]></content:encoded>
    </item>
    
    <item>
      <title>To Exit or Not Exit, the SAS Ways</title>
      <link href="/2014/09/11/to-exit-or-not-exit-the-sas-ways/"/>
      <pubDate>2014-09-11T22:55:59+00:00</pubDate>
      <author></author>
      <guid>/2014/09/11/to-exit-or-not-exit-the-sas-ways</guid>
      <content:encoded><![CDATA[<blockquote>
  <font size="1">The tragedy of life is not that it ends so soon, but that we wait so long to begin it. –by W. M. Lewis</font>
</blockquote>

<font size="1">So, which is the exit style you prefer, in the following 3 macros (which are all valid SAS codes): </font>

<blockquote>
  <font size="1" face="Courier New">/*#1 if branch*/ <br />%macro tragedy_of_life1(ds); <br />&#160;&#160;&#160; %if %sysfunc(exist(&amp;ds)) %then %do; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; proc print data=&amp;ds noobs; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; run; <br />&#160;&#160;&#160; %end; <br />&#160;&#160;&#160; <font color="#ff0000">%else %do</font>; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %put ERROR: Dataset &amp;ds not exist.; <br />&#160;&#160;&#160; %end; <br />%mend;</font>

  <font size="1" face="Courier New">/*#2 abort*/ <br />%macro tragedy_of_life2(ds); <br />&#160;&#160;&#160; %if %sysfunc(exist(&amp;ds)) ^= 1 %then %do; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %put ERROR: Dataset &amp;ds not exist.; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %<font color="#ff0000">abort</font> cancel;&#160;&#160;&#160; <br />&#160;&#160;&#160; %end;</font>

  <font size="1" face="Courier New">&#160;&#160;&#160; proc print data=&amp;ds noobs; <br />&#160;&#160;&#160; run; <br />%mend;</font>

  <font size="1" face="Courier New">/*#3 goto*/ <br />%macro tragedy_of_life3(ds); <br />&#160;&#160;&#160; %if %sysfunc(exist(&amp;ds)) ^= 1 %then %do; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %put ERROR: Dataset &amp;ds not exist.; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160; %<font color="#ff0000">goto</font> iExit;&#160;&#160;&#160; <br />&#160;&#160;&#160; %end;</font>

  <font size="1" face="Courier New">&#160;&#160;&#160; proc print data=&amp;ds noobs; <br />&#160;&#160;&#160; run;</font>

  <font size="1" face="Courier New">&#160;&#160;&#160; %iExit: <br />%mend;</font>
</blockquote>

<font size="1">I personally use #2, <em><strong>%abort cancel</strong></em>. For <strong><em>goto</em></strong> in #3, it might not a good idea to use <strong><em>goto</em></strong> statement in any cases, so I avoid it as long as I can. </font>

<font size="1">#1 is good, but you can imagine that the branches will grow dramatically if lots of exceptions are under checking. <em><strong>%abort cancel</strong></em> in #2 will best serve the purpose to isolate the blocks.</font>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
