<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809918#M319417</link>
    <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The paper you found is by Art Carpenter, and you can't go wrong with anything he writes!&amp;nbsp; BTW there is a SAS user who maintains an amazing index of SAS user group papers like that one.&amp;nbsp; If you search lexjansen.com, you'll find lots of good stuff like that.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For the time issue, if you are given a file with character values and you want to convert them to a numeric time value, you would typically use an &lt;EM&gt;informat&lt;/EM&gt; and an &lt;EM&gt;input&lt;/EM&gt; function. While SAS ships with lots of informats, I don't see one that would handle values like '7AM', unfortunately.&amp;nbsp; There is a time informat that can read values like '7:00AM' so if I were doing this, I would probably hack the data into that format, then use the time informat to read the value.&amp;nbsp; Something like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have ;
  input timechar $4. ;
  cards ;
7AM
10AM 
2PM
6PM
10PM
;

data want ;
  set have ;
  time_hacked=cats(substrn(timechar,1,anyalpha(timechar)-1),':00',substrn(timechar,anyalpha(timechar))) ;
  time=input(time_hacked,time.) ;
run ;

proc print data=want ;
  format time time. ;
run ;

proc print data=want ;
  format time timeampm. ;
run ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note that one nice thing about the INPUT function is you can tell it it to ignore invalid values and return a null value, by using the ?? modifier:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;data have ;
  input timechar $4. ;
  cards ;
7AM
10AM 
oops
2PM
6PM
10PM
;

data want ;
  set have ;
  time_hacked=cats(substrn(timechar,1,anyalpha(timechar)-1),':00',substrn(timechar,anyalpha(timechar))) ;
  time=input(time_hacked,?? time.) ;  
run ;

proc print data=want ;
  format time time. ;
run ;

proc print data=want ;
  format time timeampm. ;
run ;&lt;/PRE&gt;</description>
    <pubDate>Tue, 26 Apr 2022 17:37:16 GMT</pubDate>
    <dc:creator>Quentin</dc:creator>
    <dc:date>2022-04-26T17:37:16Z</dc:date>
    <item>
      <title>In data step, check if the value of a variable is in a list of (reusable) format values. Also change</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809784#M319343</link>
      <description>&lt;P&gt;These Qs have likely been answered before... Formats are powerful, and can be used in so many ways.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;1. Can I use them for value lists that are checked during input from a file in a datastep, and if so how? Eg, in this crude data step example:&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;if destination not in ('No Urgent Place','Home','Work') then do;&lt;BR /&gt;&amp;nbsp; &amp;nbsp;putlog 'QC_STOP: Bad value in var ' destination=;&lt;BR /&gt;&amp;nbsp; &amp;nbsp;stop;&lt;/P&gt;&lt;P&gt;end;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'd like to replace that value list in parens in the IF statement by using a defined format for those values. Then, reuse that format later in various output plots, etc.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;2. I'd like to change some values using formats as a lookup table. After checking a discrete list of hour values an input variable ('7AM','10AM','2PM','6PM','10PM') as in 1. above, I'd like to then change/map them to a newly added dataset variable representing military/24 hour as a corresponding number: 7,10,14,18,22.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I did search here and via google, but got so much related noise that I couldn't hone in on these two signals. Thanks, Peter&lt;/P&gt;</description>
      <pubDate>Mon, 25 Apr 2022 21:54:15 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809784#M319343</guid>
      <dc:creator>pspung</dc:creator>
      <dc:date>2022-04-25T21:54:15Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809871#M319393</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I read your first questions to be about using formats for data validation.&amp;nbsp; Yes, you can do this, and it's a great idea.&amp;nbsp; Ron Cody wrote an incredible book about data cleaning that includes descriptions of this approach.&amp;nbsp;&amp;nbsp;&lt;A href="https://support.sas.com/content/dam/SAS/support/en/books/codys-data-cleaning-techniques/70074_excerpt.pdf" target="_blank"&gt;https://support.sas.com/content/dam/SAS/support/en/books/codys-data-cleaning-techniques/70074_excerpt.pdf&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You could make a format like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format ; 
  value $checkdest 
    'No Urgent Place','Home','Work'='OK'
    other='BAD'
  ;
run ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Which you could use like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have ;
  input destination $15.;
  cards ;
Home
No Urgent Place
oops
Work
;
run ;

data want ;
  set have ;
  if put(destination,$checkdest.) ne 'OK' then do ;
     putlog 'QC_STOP: Bad value in var ' destination=;
     stop;
  end ;
run ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;By the way, that sort of validation check is an &lt;EM&gt;assertion&lt;/EM&gt;. You typically assert that a condition is true, and if it's not true, you write an error / abort / do something.&amp;nbsp; So if you're doing a lot of this sort of checking, it's often easier to write an %assert macro, which you would use like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data want ;
  set have ;
  %assert(put(destination,$checkdest.) = 'OK')
run ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I wrote a paper with an %assert macro, which you could easily adapt:&amp;nbsp;&lt;A href="https://www.lexjansen.com/nesug/nesug12/cc/cc31.pdf" target="_blank"&gt;https://www.lexjansen.com/nesug/nesug12/cc/cc31.pdf&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If you want to check a lot of variables like this, you can create a format that defines the valid values for each variable, use arrays or macros or whatever to loop over variables and check each variable.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I don't really understand your second question, about time values.&amp;nbsp; Typically it's best to leave time values as a SAS time (numeric value which is number of seconds since midnight) or a SAS date-time (number of seconds since midnight Jan 1, 1960).&amp;nbsp; If you have a SAS time, you can use SAS formats to display the time in different formats.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;HTH,&lt;/P&gt;
&lt;P&gt;--Q.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 26 Apr 2022 13:27:38 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809871#M319393</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2022-04-26T13:27:38Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809878#M319400</link>
      <description>&lt;P&gt;Wow &lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;,&amp;nbsp;that is SO HELPFUL for #1, and is exactly what I'm looking for. The assert macro idea is exactly the design pattern I was going for (drawing on the 14 other programming languages and related design patterns I've learned previously). I'll update my code, and reply back if there are issues.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Re #2, formats seem to be able to lookup and convert one value (or object) to another (in the Smalltalk language, an equivalent is a Dictionary object). Ie, in the code you provided, you're looking up and converting&amp;nbsp;&lt;/P&gt;&lt;PRE class=""&gt;&lt;CODE&gt;'No Urgent Place','Home','Work'='OK'&lt;/CODE&gt;&lt;/PRE&gt;&lt;P&gt;these values to 'OK', and other values to 'BAD'. In these case, they are all character values.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I want to do the same conceptually, however convert from character inputs (&lt;SPAN&gt;'7AM','10AM','2PM','6PM','10PM'&lt;/SPAN&gt;) to numbers (&lt;SPAN&gt;7,10,14,18,22&lt;/SPAN&gt;) and place them in a new numeric variable. Of course, only after the character values have survived the assert macro after reading them in from the file/cards. Thankfully you've given me some ideas of things to try, and googling "SAS format as lookup table" now is more informative -- more signal and less noise. For example,&amp;nbsp;&lt;A href="https://support.sas.com/resources/papers/proceedings15/2219-2015.pdf" target="_blank" rel="noopener"&gt;https://support.sas.com/resources/papers/proceedings15/2219-2015.pdf&lt;/A&gt;&amp;nbsp;"Table Lookup Techniques: From the Basics to the Innovative", and the USING FORMATS section.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Cody's book, the free first chapter available for download, is very helpful too. I have the book on order.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks again, so much. I welcome any additional thoughts on #2, and I'll try some things. Thanks, again Peter&lt;/P&gt;</description>
      <pubDate>Tue, 26 Apr 2022 14:04:44 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809878#M319400</guid>
      <dc:creator>pspung</dc:creator>
      <dc:date>2022-04-26T14:04:44Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809900#M319412</link>
      <description>&lt;P&gt;FORMATS convert values to text.&amp;nbsp; You use them with FORMAT and PUT statements or the PUT(), PUTN() or PUTC() functions.&lt;/P&gt;
&lt;P&gt;To create numbers you need to define an INFORMAT.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;INFORMATS convert text to values.&amp;nbsp;&amp;nbsp;You use them with INFORMAT and INPUT statements or the INPUT(), INPUTN() or INPUTC() functions.&lt;/P&gt;
&lt;P&gt;Numeric informats create numeric values.&amp;nbsp; Character informats create character values.&lt;/P&gt;
&lt;P&gt;Here is PROC FORMAT code to create an informat named TIMEX that will convert those strings into actual time values.&amp;nbsp; If you want to create the integers 7,10 etc instead then change the values on the right of the equal signs.&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;proc format ;
  invalue timex 
    '7AM' = '07:00't
    '10AM'= '10:00't
    '2PM' = '14:00't
    '6PM' = '18:00't
    '10PM'= '22:00't
  ;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 26 Apr 2022 16:44:48 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809900#M319412</guid>
      <dc:creator>Tom</dc:creator>
      <dc:date>2022-04-26T16:44:48Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809918#M319417</link>
      <description>&lt;P&gt;Hi,&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The paper you found is by Art Carpenter, and you can't go wrong with anything he writes!&amp;nbsp; BTW there is a SAS user who maintains an amazing index of SAS user group papers like that one.&amp;nbsp; If you search lexjansen.com, you'll find lots of good stuff like that.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For the time issue, if you are given a file with character values and you want to convert them to a numeric time value, you would typically use an &lt;EM&gt;informat&lt;/EM&gt; and an &lt;EM&gt;input&lt;/EM&gt; function. While SAS ships with lots of informats, I don't see one that would handle values like '7AM', unfortunately.&amp;nbsp; There is a time informat that can read values like '7:00AM' so if I were doing this, I would probably hack the data into that format, then use the time informat to read the value.&amp;nbsp; Something like:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have ;
  input timechar $4. ;
  cards ;
7AM
10AM 
2PM
6PM
10PM
;

data want ;
  set have ;
  time_hacked=cats(substrn(timechar,1,anyalpha(timechar)-1),':00',substrn(timechar,anyalpha(timechar))) ;
  time=input(time_hacked,time.) ;
run ;

proc print data=want ;
  format time time. ;
run ;

proc print data=want ;
  format time timeampm. ;
run ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Note that one nice thing about the INPUT function is you can tell it it to ignore invalid values and return a null value, by using the ?? modifier:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;data have ;
  input timechar $4. ;
  cards ;
7AM
10AM 
oops
2PM
6PM
10PM
;

data want ;
  set have ;
  time_hacked=cats(substrn(timechar,1,anyalpha(timechar)-1),':00',substrn(timechar,anyalpha(timechar))) ;
  time=input(time_hacked,?? time.) ;  
run ;

proc print data=want ;
  format time time. ;
run ;

proc print data=want ;
  format time timeampm. ;
run ;&lt;/PRE&gt;</description>
      <pubDate>Tue, 26 Apr 2022 17:37:16 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809918#M319417</guid>
      <dc:creator>Quentin</dc:creator>
      <dc:date>2022-04-26T17:37:16Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809920#M319418</link>
      <description>Thank you Tom for the great info and suggestions! I have so much to go on now. I'm going to write some more code... Peter</description>
      <pubDate>Tue, 26 Apr 2022 17:46:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809920#M319418</guid>
      <dc:creator>pspung</dc:creator>
      <dc:date>2022-04-26T17:46:56Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809921#M319419</link>
      <description>Thank you again Quentin for the great info and advice. I'm going to put this in practice, and write some code. Btw and fwiw, this is the dataset we're examining with SAS: &lt;A href="https://archive.ics.uci.edu/ml/datasets/in-vehicle+coupon+recommendation" target="_blank"&gt;https://archive.ics.uci.edu/ml/datasets/in-vehicle+coupon+recommendation&lt;/A&gt;&lt;BR /&gt;&lt;BR /&gt;Thanks again, Peter</description>
      <pubDate>Tue, 26 Apr 2022 17:48:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809921#M319419</guid>
      <dc:creator>pspung</dc:creator>
      <dc:date>2022-04-26T17:48:41Z</dc:date>
    </item>
    <item>
      <title>Re: In data step, check if the value of a variable is in a list of (reusable) format values. Also ch</title>
      <link>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809925#M319420</link>
      <description>&lt;P&gt;Resources such as the lexjansen.com site or books are so helpful, but often overwhelming to this beginner moving to intermediate programmer. Often, I don't even know how to frame the question or google search well, or have to make analogies to other concepts or design patterns in other languages that don't resonate.&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/19879"&gt;@Quentin&lt;/a&gt;&amp;nbsp;and&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/159"&gt;@Tom&lt;/a&gt;&amp;nbsp;, you've demystified this area so much for me. Thank you!&amp;nbsp; Peter&lt;/P&gt;</description>
      <pubDate>Tue, 26 Apr 2022 17:54:45 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/In-data-step-check-if-the-value-of-a-variable-is-in-a-list-of/m-p/809925#M319420</guid>
      <dc:creator>pspung</dc:creator>
      <dc:date>2022-04-26T17:54:45Z</dc:date>
    </item>
  </channel>
</rss>

