{"id":87,"date":"2019-12-09T20:02:58","date_gmt":"2019-12-09T18:02:58","guid":{"rendered":"http:\/\/jvdl.me\/wordpress\/?p=87"},"modified":"2020-01-12T14:56:52","modified_gmt":"2020-01-12T12:56:52","slug":"sas-locf-for-multiple-variables","status":"publish","type":"post","link":"https:\/\/jvdl.me\/blog\/?p=87","title":{"rendered":"SAS LOCF For Multiple Variables"},"content":{"rendered":"\n<p>It is often necessary to replace missing measurements with the closest, previous measurement. This technique is referred to as LOCF (last observation carried forward).<\/p>\n\n\n\n<p>In this example, we will create a dataset with 4 columns: subject ID, visit number, body weight, and systolic blood pressure.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sas\" class=\"language-sas line-numbers\">data have;\n\tinput ID VISIT WT SBP;\n\tcards;\n1 10 85 125\n1 20 84 .\n1 30 86 .\n1 40 . 130\n1 50 . 128\n1 60 85 .\n2 10 . 110\n2 20 90 .\n2 30 91 .\n2 40 91 123\n2 50 . .\n2 60 . 130\n;\nrun;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"368\" height=\"222\" src=\"http:\/\/jvdl.me\/wordpress\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_195848.png\" alt=\"\" class=\"wp-image-92\" srcset=\"https:\/\/jvdl.me\/blog\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_195848.png 368w, https:\/\/jvdl.me\/blog\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_195848-300x181.png 300w\" sizes=\"auto, (max-width: 368px) 100vw, 368px\" \/><figcaption>Input dataset, with subject ID, visit number, body weight, and systolic blood pressure<\/figcaption><\/figure>\n\n\n\n<p>Thereafter, we will sort the dataset to ensure it is in the order we expect. Never assume that your input will be appropriately sorted.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sas\" class=\"language-sas line-numbers\">proc sort data=have;\n\tby id visit;\nrun;<\/code><\/pre>\n\n\n\n<p>Now we will define 2 macro variables, which are simply lists of variables. The first contains the original variables available in the dataset, which will not be altered, and the second names the variables which will contain the LOCF values.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sas\" class=\"language-sas line-numbers\">%let origvars = %str(WT  SBP);\n%let locfvars = %str(WT_ SBP_);<\/code><\/pre>\n\n\n\n<p>This brings us to our final block of code. The lists of variables defined above are loaded into arrays and a loop performs the LOCF operation across all the variables defined.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"sas\" class=\"language-sas line-numbers\">data want(drop = j);\n\tset have;\n\tby id visit;\n\n\t\/*Create arrays of the variable lists*\/\n\tarray orig[*] &amp;origvars.;\n\tarray locf[*] &amp;locfvars.;\n\tretain \t      &amp;locfvars.;\n\n\tdo j = 1 to dim(orig);\n\t\tif first.id then do;\n\t\t\t\/*Set a placeholder value for initial missings*\/\n\t\t\tif orig(j) = . then locf(j) = -99;\n\t\tend;\n\n\t\t\/*Replace retained value with latest non-missing value*\/\n\t\tif not missing(orig(j)) then locf(j) = orig(j);\n\tend;\nrun;<\/code><\/pre>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"521\" height=\"222\" src=\"http:\/\/jvdl.me\/wordpress\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_200000.png\" alt=\"\" class=\"wp-image-93\" srcset=\"https:\/\/jvdl.me\/blog\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_200000.png 521w, https:\/\/jvdl.me\/blog\/wp-content\/uploads\/2019\/12\/Screenshot_20191209_200000-300x128.png 300w\" sizes=\"auto, (max-width: 521px) 100vw, 521px\" \/><figcaption>The final dataset with LOCF&#8217;ed variables, WT_ and SBP_<\/figcaption><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>It is often necessary to replace missing measurements with the closest, previous measurement. This technique is referred to as LOCF (last observation carried forward). In this example, we will create a dataset with 4 columns: subject ID, visit number, body weight, and systolic blood pressure. Thereafter, we will sort the dataset to ensure it is [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53,54],"tags":[],"class_list":["post-87","post","type-post","status-publish","format-standard","hentry","category-programming","category-sas"],"_links":{"self":[{"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/posts\/87","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=87"}],"version-history":[{"count":20,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/posts\/87\/revisions"}],"predecessor-version":[{"id":151,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=\/wp\/v2\/posts\/87\/revisions\/151"}],"wp:attachment":[{"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=87"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=87"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jvdl.me\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=87"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}