<?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 compute gap within specific time range for data with gaps and overlaps? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898494#M355128</link>
    <description>You are a genius! It took me a while to understand your code. I couldn't create this code by myself ever! How did you come up this idea? Do you know any sources to improve my SAS code skills?</description>
    <pubDate>Fri, 13 Oct 2023 14:45:24 GMT</pubDate>
    <dc:creator>SAS-questioner</dc:creator>
    <dc:date>2023-10-13T14:45:24Z</dc:date>
    <item>
      <title>How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898226#M355016</link>
      <description>&lt;P&gt;I have a data set like below:&lt;/P&gt;
&lt;PRE&gt;data have;
input ID (begindate	enddate)(:mmddyy10.) (begindate2	enddate2)(:mmddyy10.);
format begindate enddate begindate2	enddate2 mmddyy10.;
datalines;
1 3/4/2020     6/5/2020         5/30/2020    4/28/2021
1 5/16/2020    2/21/2021        5/30/2020    4/28/2021
1 7/18/2020    10/24/2020       5/30/2020    4/28/2021
1 12/30/2020   9/17/2022        5/30/2020    4/28/2021
2 6/20/2020    7/20/2020        7/12/2020    8/1/2021
2 9/1/2020     11/13/2020       7/12/2020    8/1/2021
2 1/15/2021    7/21/2021        7/12/2020    8/1/2021
3 5/20/2020    10/21/2020       3/10/2020    3/12/2021
3 8/10/2020    6/1/2021         3/10/2020    3/12/2021
;
&lt;/PRE&gt;
&lt;P&gt;The purpose is to compute the total days of gap of &lt;CODE class=" language-sas"&gt;begindate&lt;/CODE&gt;&amp;nbsp;and&amp;nbsp;&lt;CODE class=" language-sas"&gt;enddate&lt;/CODE&gt; within the range of &lt;CODE class=" language-sas"&gt;begindate2&lt;/CODE&gt; and &lt;CODE class=" language-sas"&gt;enddate2&lt;/CODE&gt;.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;For example, for ID two, based on the&amp;nbsp;&lt;CODE class=" language-sas"&gt;begindate&lt;/CODE&gt;&amp;nbsp;and&amp;nbsp;&lt;CODE class=" language-sas"&gt;enddate&lt;/CODE&gt;&amp;nbsp;several gap noticed: 7/20/2020 to 9/1/2020, and 11/13/2020 to 1/15/2021. And we also need to take the range of&amp;nbsp;&lt;CODE class=" language-sas"&gt;begindate2&lt;/CODE&gt; and &lt;CODE class=" language-sas"&gt;enddate2&lt;/CODE&gt; into consideration, therefore, another gap noticed: from 7/21/2021 to 8/1/2021. For ID three, one gap also noticed: from 3/10/2020(&lt;CODE class=" language-sas"&gt;begindate2&lt;/CODE&gt;) to 5/20/2020(&lt;CODE class=" language-sas"&gt;begindate&lt;/CODE&gt;).&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;There is one thing I probably need to mention, some dates are not in the order. If you look at the second and third row of ID 1, the second row ends at 2/21/2021, and the third row begins at 7/18/2020.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Not only I want to identify those gaps by taking account of the range of &lt;CODE class=" language-sas"&gt;begindate2&lt;/CODE&gt; and &lt;CODE class=" language-sas"&gt;enddate2&lt;/CODE&gt;, but also I need to compute the total days of those gaps. Can anyone help me with it? Thank you!&lt;/P&gt;</description>
      <pubDate>Wed, 11 Oct 2023 23:48:31 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898226#M355016</guid>
      <dc:creator>SAS-questioner</dc:creator>
      <dc:date>2023-10-11T23:48:31Z</dc:date>
    </item>
    <item>
      <title>Re: How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898232#M355018</link>
      <description>&lt;P&gt;I think that you need to walk through actually calculating the value of the desired result for at least one case explaining where each number comes from. I get confused because of the constant use of "gap" and I can't tell which context it is used in your example. Also, since you don't show the result of any of the calculations in the example I have no idea what the result should be. I am also not sure exactly what&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;You also need to describe how the "out of order" you describe is to be handled.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What actual role in this process does the variable CATE play? I don't see it mentioned in the description anywhere. If not needed then drop it.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;One suspects that the first step is identifying any gap completely ignoring your begindate2/enddate2 variables since they apparently do not change for any of the Id values. If they do, you need to provide examples.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Overlaps/continuous dates are relatively frequent questions but each has its own flavor.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 11 Oct 2023 22:43:55 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898232#M355018</guid>
      <dc:creator>ballardw</dc:creator>
      <dc:date>2023-10-11T22:43:55Z</dc:date>
    </item>
    <item>
      <title>Re: How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898235#M355019</link>
      <description>&lt;P&gt;Thank you for the reply. I will walk through the whole process. First of all, the&amp;nbsp;&lt;SPAN&gt;begindate2/enddate2 do not change for any of the ID values because it's the standard time range that I am interested in. Begindate/enddate are the time range for a product that each person owned, they might own it for different time range. What I want to do is to find out, during the&amp;nbsp;begindate2/enddate2, are there any time gaps for&amp;nbsp;Begindate/enddate.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;I will take ID 2 as example to demonstrate the process:&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;1, we use&amp;nbsp;begindate2/enddate2 as the standard time range, which is from 7/12/2020 to 8/1/2021.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;2, the first ID 2's Begindate/enddate are 6/20/2020 to 7/20/2020, 6/20/2020 is before 7/12/2020, and 7/20/2020 is before 8/1/2021, so there is no gap.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;3, the second ID 2's&amp;nbsp;Begindate/enddate are 9/1/2020 to 11/13/2020, compare to the first ID 2's&amp;nbsp;Begindate/enddate, we notice that the enddate is 7/20/2020, but the begindate is 9/1/2020, so we compute the gap of days are (9/1/2020-7/20/2020) = 41.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;4, the third ID 2's Begindate/enddate are 1/15/2021 to 7/21/2021, we noticed two time gap: the first gap is (1/15/2021-11/13/2020)= 53, and the second gap is (8/1/2021[enddate2]-7/21/2021)=9.&amp;nbsp;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;5. the total time gap within the range&amp;nbsp;7/12/2020 to 8/1/2021 are 41+53+9=103.&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;That's pretty much what I thought the process might be. And the reason that I mention the time order is because I notice that some enddate are later than the next begindate, I used to try the&amp;nbsp;&lt;CODE class=" language-sas"&gt;lag(enddate)&lt;/CODE&gt;&amp;nbsp;, because the enddate are later than the next begindate, I don't think that statement works for this kind of situation?&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN&gt;Yeah, the CATE $ doesn't matter here, so I have removed it in the post. Thank you for taking the time!&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Thu, 12 Oct 2023 00:17:43 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898235#M355019</guid>
      <dc:creator>SAS-questioner</dc:creator>
      <dc:date>2023-10-12T00:17:43Z</dc:date>
    </item>
    <item>
      <title>Re: How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898363#M355063</link>
      <description>&lt;P&gt;Since you want total gaps days, it seems you want only one observation per ID, with values for the ID, BEGINDATE2, ENDDATE2, and new variables TOTAL_DAYS_IN_RANGE, TOTAL_GAP_DAYS, and N_GAPS.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Of course, this assumes that each ID has a constant pair of BEGINDATE2 and ENDDATE2 for all observations.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The technique is to create a history array, indexed by date, ranging from begindate2 through enddate2.&amp;nbsp; The array will have dummy variables, with a value of 1 for days covering all pairs of begindate/enddate within the begdate2/enddate2 &lt;STRIKE&gt;history&lt;/STRIKE&gt; range, and zero for all other dates within the begdate2/enddate2 range (i.e. 0 for all gap dates).&amp;nbsp; And dates in the array but outside of begindate2/enddate2, are all set to missing.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data have;
  input ID (begindate	enddate)(:mmddyy10.) (begindate2	enddate2)(:mmddyy10.);
  format begindate enddate begindate2	enddate2 mmddyy10.;
datalines;
1 3/4/2020     6/5/2020         5/30/2020    4/28/2021
1 5/16/2020    2/21/2021        5/30/2020    4/28/2021
1 7/18/2020    10/24/2020       5/30/2020    4/28/2021
1 12/30/2020   9/17/2022        5/30/2020    4/28/2021
2 6/20/2020    7/20/2020        7/12/2020    8/1/2021
2 9/1/2020     11/13/2020       7/12/2020    8/1/2021
2 1/15/2021    7/21/2021        7/12/2020    8/1/2021
3 5/20/2020    10/21/2020       3/10/2020    3/12/2021
3 8/10/2020    6/1/2021         3/10/2020    3/12/2021
run;

%let beg_study=01jan2020;
%let end_study=01jan2023;
%let study_length=%sysfunc(intck(day,"&amp;amp;beg_study"d,"&amp;amp;end_study"d));
%put _user_;

data want (keep=id begindate2 enddate2  total_: n_gaps);
  set have;
  by id ;
  array history {%sysevalf("01jan2020"d):%sysevalf("31dec2022"d)} _temporary_;

  if first.id then do;
    call missing(of history{*});
    do d=begindate2 to enddate2;
      history{d}=0;
    end;
  end;
  do d=max(begindate,begindate2) to min(enddate,enddate2);
    history{d}=1;
  end;

  if last.id;
  length strng $&amp;amp;study_length ;
  total_days_in_range = enddate2+1-begindate2;
  total_gap_days = total_days_in_range- sum(of history{*});

  strng=compress(cats(of history{*}),'.');    *Remove .'s and left justify*;
  n_gaps=countw(trim(strng),'1');             *Count gaps, but ignore trailing blanks*;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;At the end of each ID, just subtract the sum of 1's for (total nongap days) from the number of days in the begindate2/enddate2 range.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;The n_gaps is calculated via this approach.&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Make a concatenated string of .'s, 0',s and 1.s from the history array:&amp;nbsp; &amp;nbsp;&lt;STRONG&gt;&lt;FONT face="courier new,courier"&gt;&lt;EM&gt;cats(of history{*})&lt;/EM&gt;&lt;/FONT&gt;&lt;/STRONG&gt;&lt;/LI&gt;
&lt;LI&gt;Remove all the .'s, and left justify:&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;FONT face="courier new,courier"&gt;&lt;EM&gt;&lt;STRONG&gt;compress(cats(of history{*}),'.')&lt;/STRONG&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;LI&gt;Trim the trailing blanks:&amp;nbsp; &amp;nbsp; &lt;FONT face="courier new,courier"&gt;&lt;EM&gt;&lt;STRONG&gt;trim(strng)&lt;/STRONG&gt;&lt;/EM&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&lt;/LI&gt;
&lt;LI&gt;Count the number of words (where 1's are viewed as word separators.:&lt;BR /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;FONT face="courier new,courier"&gt;&lt;EM&gt;&lt;STRONG&gt;countw(trim(strng&lt;/STRONG&gt;&lt;STRONG&gt;),'1')&lt;/STRONG&gt;&lt;/EM&gt;&lt;/FONT&gt;&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;In this case, a "word" is a string of zeroes, bounded on each side by a one, or by the beginning or end of the string.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Fri, 13 Oct 2023 22:25:52 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898363#M355063</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2023-10-13T22:25:52Z</dc:date>
    </item>
    <item>
      <title>Re: How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898494#M355128</link>
      <description>You are a genius! It took me a while to understand your code. I couldn't create this code by myself ever! How did you come up this idea? Do you know any sources to improve my SAS code skills?</description>
      <pubDate>Fri, 13 Oct 2023 14:45:24 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898494#M355128</guid>
      <dc:creator>SAS-questioner</dc:creator>
      <dc:date>2023-10-13T14:45:24Z</dc:date>
    </item>
    <item>
      <title>Re: How to compute gap within specific time range for data with gaps and overlaps?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898584#M355175</link>
      <description>&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/376504"&gt;@SAS-questioner&lt;/a&gt;&amp;nbsp;wrote:&lt;BR /&gt;... stuff deleted ...&lt;BR /&gt;How did you come up this idea? ...&lt;/BLOCKQUOTE&gt;
&lt;P class="1697253639940"&gt;Forget the functions for generating N_GAPS.&amp;nbsp; The tool of primary interest here (the "idea") is the HISTORY array.&amp;nbsp; &amp;nbsp;The idea of using an array indexed by dates is an old one, but (to my knowledge) is not a technique taught in SAS programming classes.&amp;nbsp; (Only so much can fit in the syllabus).&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;There are two important aspects of this array:&amp;nbsp; &amp;nbsp;&lt;/P&gt;
&lt;UL class="lia-list-style-type-square"&gt;
&lt;LI class="1697253639940"&gt;It is declared as _TEMPORARY_, so
&lt;UL class="lia-list-style-type-square"&gt;
&lt;LI class="1697253639940"&gt;It does not create variables that will be in the new data set.&lt;/LI&gt;
&lt;LI class="1697253639940"&gt;Its values are automatically RETAINED from obs to obs, so you can build the array over a sequence of observations.&lt;/LI&gt;
&lt;/UL&gt;
&lt;/LI&gt;
&lt;LI&gt;The array has lower and upper bounds corresponding to the dates 01jan2020 and 31dec2022.&lt;/LI&gt;
&lt;/UL&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;Regarding the lower/upper bounds point:&amp;nbsp; Usually you can declare an array like&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;array history {1096} _temporary_;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P class="1697253639940"&gt;which has elements history{1} through history{1096}.&lt;/P&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;But you can also declare an array like this:&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;array history {21915:23010} _temporary_ ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P class="1697253639940"&gt;which also has 1096 elements, but the leftmost element is history{21915} (not history{1}) and the rightmost is history{23010} instead of history{1096}.&lt;/P&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;And why did I choose those values as the bounds?&amp;nbsp; Because they are the SAS date values for 01jan2020 and 31dec2022 (which I took as the likely earliest and latest dates in your study).&lt;/P&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;Unfortunately, SAS doesn't accept this intuitively obvious syntax&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;array history {"01jan2020"d:"31dec2022"d} _temporary_ ;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P class="1697253639940"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class="1697253639940"&gt;So, because I didn't want to manually determine the actual date values 21915 and 23010, I used the macro function %sysevalf to do it for me.&amp;nbsp; But the macro function is just icing on the cake.&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Sat, 14 Oct 2023 03:50:41 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/How-to-compute-gap-within-specific-time-range-for-data-with-gaps/m-p/898584#M355175</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2023-10-14T03:50:41Z</dc:date>
    </item>
  </channel>
</rss>

