<?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: How to count unique character variable values across multiple variables and observations in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658243#M197280</link>
    <description>&lt;P&gt;First, transpose your dataset from wide to long, by study_id and a variable that identifies the encounter (remove the missing values with a where= dataset option). Then you can use a count(distinct) in SQL.&lt;/P&gt;
&lt;P&gt;Long datasets are always easier to work with.&lt;/P&gt;</description>
    <pubDate>Sat, 13 Jun 2020 04:14:13 GMT</pubDate>
    <dc:creator>Kurt_Bremser</dc:creator>
    <dc:date>2020-06-13T04:14:13Z</dc:date>
    <item>
      <title>How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658184#M197255</link>
      <description>&lt;P&gt;Hello everyone, long time lurker, first time poster here.&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I have a medical claims data base with multiple encounters (up to 1000 or so) for each individual. In this data set I have 24 diagnosis character variables with the naming convention diag_1 - diag_24, and these variables are filled sequentially (doctor listed between 0 and 24 diagnoses per encounter) so that if the doctor identified 8 diagnosis codes, these would appear individually in diag_1, diag_2, etc. until diag_8, after which diag_9 - diag_24 would be blank. Please note that there are often duplicate diagnosis codes across the observations for the same individual, however never within observations.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;My challenge is to create a continuous variable of "clinical complexity" of a certain type. This variable would include the total number of unique diagnoses included in any one of the patient's records in the 24 diagnosis variables. I have the relevant list of diagnoses in a macro variable (&amp;amp;diag_list).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;A highly simplified version of the data set would look like this:&lt;/P&gt;&lt;LI-CODE lang="markup"&gt; data encounters(label='medical encounters');
   infile datalines dsd truncover;
   input study_id:8. diag_1:$200. diag_2:$200. diag_3:$200.;
 datalines;
 101 F341 F41 F340
 101 F340 F49 
 101 F341 F22 F12
 102 F4689 F410 F011
 102 F341 F410 F340
 ;;;;&lt;/LI-CODE&gt;&lt;P&gt;Assuming all of these diagnosis codes are included in the $diag_list macro variable, I would like to create a continuous variable that would be 4 for study_id 101 and 5 for study_id 102.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I did find some code from&amp;nbsp;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/4954"&gt;@Astounding&lt;/a&gt; suggested on a similar question where the data set was only one observation per individual. This code works to count unique diagnoses within observations, but not across observations as well:&lt;/P&gt;&lt;PRE&gt;data want;
	set have;
	array col {24} dsc_diag_1-dsc_diag_24;
	array new {24} $20  _temporary_;
		do _n_=1 to 24;
		   new{_n_} = col{_n_};
		end;
	call sortc(of new{*});
	count = (new{1} &amp;gt; ' ');
		do _n_=2 to 24;
		   if new{_n_}  ne new{_n_-1} then count + 1;
		end;
run;&lt;/PRE&gt;&lt;P&gt;Any help with this would be greatly appreciated, I've looked at many posts to see if this topic had been covered yet. I'm sure it has but I cannot find anything that helps me in this particular situation. This is the first time I've been really stumped even after reading prior posts and various documents, SUGI's, etc.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks!&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jun 2020 19:36:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658184#M197255</guid>
      <dc:creator>montgomerybarre</dc:creator>
      <dc:date>2020-06-12T19:36:54Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658201#M197258</link>
      <description>&lt;P&gt;One way:&lt;/P&gt;
&lt;PRE&gt;data encounters(label='medical encounters');
   infile datalines  truncover;
   input study_id:8. diag_1:$200. diag_2:$200. diag_3:$200.;
datalines;
101 F341 F41 F340
101 F340 F49 
101 F341 F22 F12
102 F4689 F410 F011
102 F341 F410 F340
;;;;

data long;
   set encounters;
   array d diag_: ;
   length onediag $ 200;
   do i=1 to dim(d);
      if not missing(d[i]) then do;
         onediag=d[i];
         output;
      end;
   end;
   keep study_id onediag;
run;

proc sql;
   create table dcount as
   select study_id, count(*) as diagcount
   from (select distinct study_id,onediag
          from long)
   group by study_id
   ;
quit;

&lt;/PRE&gt;
&lt;P&gt;I removed the DSD option from the Infile because with this data and the assigned lengths of your variable it caused all of the data to be "invalid".&lt;/P&gt;
&lt;P&gt;The long set is a bit different than proc transpose would generate with only one code per record.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Another way to do the count would be two proc freqs.&lt;/P&gt;
&lt;PRE&gt;proc freq data=long noprint;
   tables study_id*onediag/ out=temp;
run;
proc freq data=temp noprint;
   tables study_id /out=freqcount(drop=percent) ;
run;&lt;/PRE&gt;
&lt;P&gt;or sort Long to remove duplicates of study_id onediag&lt;/P&gt;
&lt;P&gt;Sort of depends on other things you might want to know about the data in between step.&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jun 2020 20:08:11 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658201#M197258</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2020-06-12T20:08:11Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658210#M197264</link>
      <description>&lt;P&gt;A HASH object is very effective for counting unique values (.NUM_ITEMS) when the variable is a key, and for entering into membership via .ADD()&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;A logic statement with a compiled IN operation is said to be one of the fastest methods for checking set membership.
&lt;UL&gt;
&lt;LI&gt;Use IN to see if a doctors diagnosis is one that is of interest (for say a &lt;STRONG&gt;study&lt;/STRONG&gt;)&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;LI&gt;Use HASH to track unique diagnosis in the study list&lt;/LI&gt;
&lt;LI&gt;Use another HASH to track non-study diagnoses (for yucks)&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;Example:&lt;/P&gt;
&lt;P&gt;Data for 1,000 patients having random number of visits and random number of random diagnoses.&lt;/P&gt;
&lt;LI-SPOILER&gt;
&lt;PRE&gt;data have;
  call streaminit(123);
  do patid = 1 to 100;
    date = today() - rand('integer',250,1300);
    top = rand('integer',5,1000);
    do index = 1 by 1 while (date &amp;lt;= today() and index &amp;lt;= top);
      array diag(24);
      do dindex = 1 to rand('integer',1,rand('integer', dim(diag)));
        * possible repeated diagnosis in row dont matter in this example;
        * so dont try to prevent them;
        diag(dindex) = rand('integer',1,1000);
      end;
      visitid + 1;
      output;
      date + rand('integer',0,3);
      call missing (of diag(*));
    end;
  end;
  keep patid date diag: visitid;
  format date yymmdd10.;
run;&lt;BR /&gt;&lt;BR /&gt;* visit count distribution, just a look see;&lt;BR /&gt;proc sql;&lt;BR /&gt;  create table freq1 as &lt;BR /&gt;  select &lt;BR /&gt;    visit_count, count(*) as freq from &lt;BR /&gt;    ( select &lt;BR /&gt;      patid, count(*) as visit_count from have group by patid&lt;BR /&gt;    )&lt;BR /&gt;    group by visit_count&lt;BR /&gt;  ;&lt;/PRE&gt;
&lt;/LI-SPOILER&gt;
&lt;P&gt;Per patient, count number of diagnoses matching the study list across all diagnoses of all visits.&lt;/P&gt;
&lt;PRE&gt;%let study_diagnoses = 2,5,11,17,23,31,43,53,61,71,79,89;

data want;
  if _n_ = 1 then do;
    call missing(dx);
    declare hash study_dx();
    declare hash other_dx();
    study_dx.defineKey('dx');
    study_dx.defineDone();
    other_dx.defineKey('dx');
    other_dx.defineDone();
  end;

  do until (last.patid);

    set have;
    by patid;

    array dxs diag:;

    do index = 1 to dim(dxs) while (not missing(dxs(index)));

      dx = dxs(index);
      if dx in (&amp;amp;study_diagnoses)
        then rc = study_dx.add();
        else rc = other_dx.add();

    end;

  end;

  dx_in_study_count = study_dx.num_items;
  dx_not_in_study_count = other_dx.num_items;

  study_dx.clear();
  other_dx.clear();

  keep patid dx_:;
run;&lt;/PRE&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper lia-image-align-inline" image-alt="RichardADeVenezia_0-1591994707065.png" style="width: 400px;"&gt;&lt;img src="https://communities.sas.com/t5/image/serverpage/image-id/42900iE3A07581B64CC883/image-size/medium?v=v2&amp;amp;px=400" role="button" title="RichardADeVenezia_0-1591994707065.png" alt="RichardADeVenezia_0-1591994707065.png" /&gt;&lt;/span&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 12 Jun 2020 20:45:27 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658210#M197264</guid>
      <dc:creator>RichardDeVen</dc:creator>
      <dc:date>2020-06-12T20:45:27Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658243#M197280</link>
      <description>&lt;P&gt;First, transpose your dataset from wide to long, by study_id and a variable that identifies the encounter (remove the missing values with a where= dataset option). Then you can use a count(distinct) in SQL.&lt;/P&gt;
&lt;P&gt;Long datasets are always easier to work with.&lt;/P&gt;</description>
      <pubDate>Sat, 13 Jun 2020 04:14:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/658243#M197280</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2020-06-13T04:14:13Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/660100#M197624</link>
      <description>&lt;P&gt;Hi Kurt,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Than ks for your reply! When you say long form data set, I'm a bit confused as there are already multiple observations for every individual (my definition of long). Do you mean essentially to transpose the 24 diagnosis variables to basically make the data set 23 variables 'less-wide' and 23 observations longer?&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;If so, I think this makes good sense. Thanks for your input; I'm repeatedly asked to make this data one record per individual, so I did not think to make it longer.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Best,&lt;/P&gt;&lt;P&gt;Barrett&lt;/P&gt;</description>
      <pubDate>Tue, 16 Jun 2020 16:22:57 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/660100#M197624</guid>
      <dc:creator>montgomerybarre</dc:creator>
      <dc:date>2020-06-16T16:22:57Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/661202#M197700</link>
      <description>&lt;P&gt;Here's an illustration:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data encounters(label='medical encounters');
infile datalines dsd dlm=" " truncover;
input study_id :$3. (diag_1-diag_3) (:$10.);
n = _n_; /* add an identifier for individual observations */
datalines;
101 F341 F41 F340
101 F340 F49 
101 F341 F22 F12
102 F4689 F410 F011
102 F341 F410 F340
;

proc transpose
  data=encounters
  out=long (drop=n _name_ where=(col1 ne " "))
;
by study_id n;
var diag:;
run;

proc sql;
create table want as
  select
    study_id,
    count(distinct col1) as complexity
  from long
  group by study_id
;
quit;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;You only need to add the selection of diagnosis codes; since you didn't show the layout of your macro variable, I did not include that.&lt;/P&gt;
&lt;P&gt;But you can see the advantage of the long structure for all kinds of counting, summing or other group-based analysis. It is also expected in SAS procedures; as an example, you can't tell SGPLOT to do horizontal sums before plotting.&lt;/P&gt;
&lt;P&gt;I have encountered just two reasons for a wide layout: human consumption and regression analysis, where lots of yes/no indicators are needed for an individual object. So the wide layout usually shows up at the end of my programs, when needed.&lt;/P&gt;</description>
      <pubDate>Wed, 17 Jun 2020 08:16:56 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/661202#M197700</guid>
      <dc:creator>Kurt_Bremser</dc:creator>
      <dc:date>2020-06-17T08:16:56Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663292#M197963</link>
      <description>&lt;P&gt;Very helpful, thanks for these bits of wisdom!&lt;/P&gt;</description>
      <pubDate>Thu, 18 Jun 2020 19:34:02 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663292#M197963</guid>
      <dc:creator>montgomerybarre</dc:creator>
      <dc:date>2020-06-18T19:34:02Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663295#M197965</link>
      <description>I can't get this to work. The main reason is that I'm not sure what your dx variable is referring to? I have 24 diagnosis variables that are included in your program with the diag:, therefore I'm not sure what the dx and dxs are referring to? SAS tells me I'm defining an array with zero elements, and I agree!</description>
      <pubDate>Thu, 18 Jun 2020 19:41:08 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663295#M197965</guid>
      <dc:creator>montgomerybarre</dc:creator>
      <dc:date>2020-06-18T19:41:08Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663556#M198098</link>
      <description>&lt;P&gt;&lt;BR /&gt;I found this to be the best and easiest solution to implement. I just added a few extra steps to make sure that individuals with 0 diagnoses were identified as 0 and not as missing.&lt;/P&gt;</description>
      <pubDate>Fri, 19 Jun 2020 17:26:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663556#M198098</guid>
      <dc:creator>montgomerybarre</dc:creator>
      <dc:date>2020-06-19T17:26:24Z</dc:date>
    </item>
    <item>
      <title>Re: How to count unique character variable values across multiple variables and observations</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663605#M198129</link>
      <description>&lt;P&gt;For the sake of simplifying sample data generation (in the spoiler) diagnoses are just integers.&amp;nbsp; Likewise simplifying the assignment of the macro variable whose value is a list of the 'values of interest' needed for some study.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;%let study_diagnoses = 2,5,11,17,23,31,43,53,61,71,79,89;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For the case of character diagnoses it might look like&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;%let study_diagnoses = `F341', 'F41', 'F340', 'F998', 'F1234', 'F123', 'F12';&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the list (i.e the relevant ones) has a more patterned or complex origin you might be using &lt;CODE&gt;DATA / SYMPUT('&amp;lt;macrovar&amp;gt;',&lt;/CODE&gt; or &lt;CODE&gt;SQL / INTO :&amp;lt;macrovar&amp;gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;dx&lt;/CODE&gt; is implicitly added to the PDV as a number, and is the host variable for the hash key and will be used to 'extract' values from the &lt;CODE&gt;dxs&lt;/CODE&gt; array when interacting with the hash object.&lt;/P&gt;
&lt;PRE&gt;call missing(dx);&lt;/PRE&gt;
&lt;P&gt;For the case of character diagnoses (&lt;CODE&gt;DIAG:&lt;/CODE&gt;) the host variable type needs to correspond. Replace the&amp;nbsp;&lt;CODE&gt;call MISSING&lt;/CODE&gt;&amp;nbsp;with a statement such as&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;LI-CODE lang="markup"&gt;length dx $8;&lt;/LI-CODE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The elements of array &lt;CODE&gt;dxs&lt;/CODE&gt; are the variables whose names start with &lt;CODE&gt;diag&lt;/CODE&gt;&lt;/P&gt;
&lt;PRE&gt; array dxs diag:;&lt;/PRE&gt;
&lt;P&gt;The diagnoses is my generated sample data are numeric, so the original sample code won't be appropriate to your actual data until the&amp;nbsp;&lt;CODE&gt;dx&lt;/CODE&gt; type is changed to character.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;When looping over the &lt;CODE&gt;dxs&lt;/CODE&gt;&amp;nbsp;array pull out a diagnosis, check for it's relevance, and track its presence as a hash entry.&lt;/P&gt;
&lt;PRE&gt;      dx = dxs(index);
      if dx in (&amp;amp;study_diagnoses)
        then rc = study_dx.add();
        else rc = other_dx.add();&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Hope this explanation clarifies the technique and makes it applicable to your use case.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 19 Jun 2020 20:59:15 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-count-unique-character-variable-values-across-multiple/m-p/663605#M198129</guid>
      <dc:creator>RichardDeVen</dc:creator>
      <dc:date>2020-06-19T20:59:15Z</dc:date>
    </item>
  </channel>
</rss>

