<?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: Converting irregular time-series observations to periodical observations? in SAS Programming</title>
    <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414678#M101614</link>
    <description>&lt;P&gt;x&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Why are you doing a PROC SORT, by fixed_time/timestamp?&lt;BR /&gt;Fixed_time is a monotonic step function of timestamp.&amp;nbsp; So if the incoming data is sorted by timestamp, the result is already sorted by fixed_time/timestamp.&amp;nbsp; It would be a waste of disk input/output activity and time.&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;If all you want is the last valid value at a given fixed_time, you can do that selection in the first data step.&amp;nbsp; You don't really need an extra DATA step - again a waste of disk activity.&lt;BR /&gt;&lt;BR /&gt;But if you prefer that technique, you can eliminate the disk activity by making the first data set a &lt;EM&gt;&lt;STRONG&gt;dataset view&lt;/STRONG&gt;&lt;/EM&gt;, and then read it to make the second data set as a &lt;EM&gt;&lt;STRONG&gt;dataset file&lt;/STRONG&gt;&lt;/EM&gt;, as in:&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data need / view=need;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set trades .....;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .....&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; run;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data want;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set need;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; by fixed_time;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if last.fixed_time;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; run;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;A data set view doesn't write data to disk,&amp;nbsp; it processes the data only when&amp;nbsp;referenced in a later&amp;nbsp;step.&amp;nbsp; Then instead of writing to disk, it streams the data to the calling step.&amp;nbsp;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As to holes in your timestamps, you can change the DATA WANT step to&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;data want (drop=nxt_:);&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp; merge need&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; need (firstobs=2 keep=fixed_time rename=(fixed_time=nxt_fixed_time))&amp;nbsp; end=end_of_merge;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp; if end_of_merge=0 then do&amp;nbsp;fixed_time=fixed_time to nxt_fixed_time-2 by 2;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;run;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;</description>
    <pubDate>Sun, 19 Nov 2017 19:18:54 GMT</pubDate>
    <dc:creator>mkeintz</dc:creator>
    <dc:date>2017-11-19T19:18:54Z</dc:date>
    <item>
      <title>Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/413843#M101326</link>
      <description>&lt;P&gt;Hi,&amp;nbsp;&lt;/P&gt;&lt;P&gt;I'm writing a thesis&amp;nbsp;using tick-by-tick stock exchange data with "time irregular" trade price observations.&lt;/P&gt;&lt;P&gt;I want to "fix" the observation to periodical observations&amp;nbsp;&lt;U&gt;relative&lt;/U&gt; to the trade day open time (denoted as OpenFlag).&lt;/P&gt;&lt;P&gt;I used Proc SQL to do this conversion (see attached below / attached file), but it is very inefficient (my dataset is big with ~500,000 observations each day * 3,000 days * 30 variables).&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Can this be done more efficiently using Proc Expand or Proc Timeseries? I already burned one hard disk trying ....&amp;nbsp;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;I appriciate any help I can get.&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks,&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Saggi&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Here is the code I use:&lt;/P&gt;&lt;P&gt;/* Create example dataset */&lt;BR /&gt;Data Trades;&lt;BR /&gt;input TimeStamp time9. X OpenFlag;&lt;BR /&gt;Format TimeStamp time9.;&lt;BR /&gt;datalines;&lt;BR /&gt;09:00:00 61 0&lt;BR /&gt;09:00:01 98 0&lt;BR /&gt;09:00:02 54 0&lt;BR /&gt;09:00:03 93 0&lt;BR /&gt;09:00:04 83 0&lt;BR /&gt;09:00:10 42 0&lt;BR /&gt;09:00:11 62 1&lt;BR /&gt;09:00:12 46 0&lt;BR /&gt;09:00:13 60 0&lt;BR /&gt;09:00:14 92 0&lt;BR /&gt;09:00:15 54 0&lt;BR /&gt;09:00:16 29 0&lt;BR /&gt;;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;/*Create Fix 2 seconds time interval table */&lt;BR /&gt;Data FT;&lt;BR /&gt;set Trades;&lt;BR /&gt;if OpenFlag = 1;&lt;BR /&gt;rename TimeStamp=OpenTime;&lt;BR /&gt;run;&lt;BR /&gt;Data FT;&lt;BR /&gt;set FT;&lt;BR /&gt;Retain OpenTime FTime;&lt;BR /&gt;Do i= -60 to 60 by 2;&lt;BR /&gt;FTime=OpenTime+i;&lt;BR /&gt;output;&lt;BR /&gt;end;&lt;BR /&gt;Format FTime time9.;&lt;BR /&gt;Keep OpenTime FTime;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;/* Merge and create a fix time trades dataset */&lt;BR /&gt;PROC SQL;&lt;BR /&gt;CREATE TABLE WORK.FT_2Sec_Trades AS&lt;BR /&gt;SELECT t1.FTime,&lt;BR /&gt;t2.TimeStamp,&lt;BR /&gt;t2.OpenFlag,&lt;BR /&gt;t2.X&lt;BR /&gt;FROM FT t1&lt;BR /&gt;LEFT JOIN Trades t2 ON (t1.FTime &amp;gt;= t2.TimeStamp)&lt;BR /&gt;Group by t1.FTime having t2.TimeStamp = max(t2.TimeStamp)&lt;BR /&gt;ORDER BY t1.FTime,&lt;BR /&gt;t2.TimeStamp;&lt;BR /&gt;QUIT;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Wed, 15 Nov 2017 23:40:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/413843#M101326</guid>
      <dc:creator>SK12376574</dc:creator>
      <dc:date>2017-11-15T23:40:19Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414352#M101515</link>
      <description>&lt;P&gt;For dealing with sorted large datasets, and producing datasets compare the sort key in one record to neighboring records, I&amp;nbsp; have never seen SQL come anywhere close to a well-formed data step:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;Data Trades;
input TimeStamp time9. X OpenFlag;
Format TimeStamp time9.;
datalines;
09:00:00 61 0
09:00:01 98 0
09:00:02 54 0
09:00:03 93 0
09:00:04 83 0
09:00:10 42 0
09:00:11 62 1
09:00:12 46 0
09:00:13 60 0
09:00:14 92 0
09:00:15 54 0
09:00:16 29 0
;
run;

data want;
  set trades (where=(openflag=1))
      trades (where=(openflag=0));
  /*by ticker;*/

  if openflag=1 then opentime=timestamp;
  retain opentime;
  format opentime time8.0;

  if abs(timestamp-opentime)&amp;lt;=60;
  fixed_time= round(1+timestamp-opentime,2);
  format fixed_time time8.0;
run;
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This program assumes the data are sorted by timestamp. If the data are actually sorted by&amp;nbsp; ticker/time, put&amp;nbsp; in a "by ticker;" statement.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;Edits:&lt;/P&gt;
&lt;P&gt;If your data is sorted by&amp;nbsp;&amp;nbsp;ticker/timestamp, then&amp;nbsp; use the "by ticker;" statement.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Also this program assumes 1 &lt;EM&gt;&lt;STRONG&gt;openflag=1&lt;/STRONG&gt;&lt;/EM&gt; record per ticker.&lt;/P&gt;</description>
      <pubDate>Fri, 17 Nov 2017 14:10:50 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414352#M101515</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2017-11-17T14:10:50Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414675#M101612</link>
      <description>&lt;P&gt;Thanks for the prompt reply.&lt;/P&gt;&lt;P&gt;Since I need the code to extrapolate the&amp;nbsp;&lt;U&gt;last known&lt;/U&gt; value, I changed the code as following.&lt;/P&gt;&lt;P&gt;As you can see there are two "missing" observations 09:00:07 and 09:00:09 both of them should get the last known value of x=83.&lt;/P&gt;&lt;P&gt;I will appreciate any help in filling out the missing observation in&amp;nbsp; an efficient way (I used proc expand but it is sort of a black box for me).&lt;/P&gt;&lt;P&gt;Thanks,&amp;nbsp;&lt;/P&gt;&lt;P&gt;SK&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Data Trades;&lt;BR /&gt;input TimeStamp time9. X OpenFlag;&lt;BR /&gt;Format TimeStamp time9.;&lt;BR /&gt;datalines;&lt;BR /&gt;09:00:00 61 0&lt;BR /&gt;09:00:01 98 0&lt;BR /&gt;09:00:02 54 0&lt;BR /&gt;09:00:03 93 0&lt;BR /&gt;09:00:04 83 0&lt;BR /&gt;09:00:10 42 0&lt;BR /&gt;09:00:11 62 1&lt;BR /&gt;09:00:12 46 0&lt;BR /&gt;09:00:13 60 0&lt;BR /&gt;09:00:14 92 0&lt;BR /&gt;09:00:15 54 0&lt;BR /&gt;09:00:16 29 0&lt;BR /&gt;;&lt;BR /&gt;run;&lt;BR /&gt;data want;&lt;BR /&gt;set trades (where=(openflag=1))&lt;BR /&gt;trades (where=(openflag=0));&lt;BR /&gt;if openflag=1 then opentime=timestamp;&lt;BR /&gt;retain opentime;&lt;BR /&gt;format opentime time8.0;&lt;BR /&gt;fixed_time=opentime+ceil((timestamp-opentime)/2)*2;&lt;BR /&gt;format fixed_time time8.0;&lt;BR /&gt;run;&lt;BR /&gt;Proc Sort data=want;&lt;BR /&gt;by fixed_time timestamp;&lt;BR /&gt;run;&lt;BR /&gt;Data Want;&lt;BR /&gt;set want;&lt;BR /&gt;by fixed_time timestamp;&lt;BR /&gt;if last.fixed_time;&lt;BR /&gt;run;&lt;/P&gt;</description>
      <pubDate>Sun, 19 Nov 2017 17:03:18 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414675#M101612</guid>
      <dc:creator>SK12376574</dc:creator>
      <dc:date>2017-11-19T17:03:18Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414678#M101614</link>
      <description>&lt;P&gt;x&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Why are you doing a PROC SORT, by fixed_time/timestamp?&lt;BR /&gt;Fixed_time is a monotonic step function of timestamp.&amp;nbsp; So if the incoming data is sorted by timestamp, the result is already sorted by fixed_time/timestamp.&amp;nbsp; It would be a waste of disk input/output activity and time.&lt;BR /&gt;&lt;BR /&gt;&lt;/LI&gt;
&lt;LI&gt;If all you want is the last valid value at a given fixed_time, you can do that selection in the first data step.&amp;nbsp; You don't really need an extra DATA step - again a waste of disk activity.&lt;BR /&gt;&lt;BR /&gt;But if you prefer that technique, you can eliminate the disk activity by making the first data set a &lt;EM&gt;&lt;STRONG&gt;dataset view&lt;/STRONG&gt;&lt;/EM&gt;, and then read it to make the second data set as a &lt;EM&gt;&lt;STRONG&gt;dataset file&lt;/STRONG&gt;&lt;/EM&gt;, as in:&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data need / view=need;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set trades .....;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .....&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; run;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; data want;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set need;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; by fixed_time;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if last.fixed_time;&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; run;&lt;/FONT&gt;&lt;BR /&gt;&lt;BR /&gt;A data set view doesn't write data to disk,&amp;nbsp; it processes the data only when&amp;nbsp;referenced in a later&amp;nbsp;step.&amp;nbsp; Then instead of writing to disk, it streams the data to the calling step.&amp;nbsp;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As to holes in your timestamps, you can change the DATA WANT step to&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;data want (drop=nxt_:);&lt;/FONT&gt;&lt;BR /&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp; merge need&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; need (firstobs=2 keep=fixed_time rename=(fixed_time=nxt_fixed_time))&amp;nbsp; end=end_of_merge;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp; if end_of_merge=0 then do&amp;nbsp;fixed_time=fixed_time to nxt_fixed_time-2 by 2;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; output;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;end;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="courier new,courier"&gt;run;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;run;&lt;/P&gt;</description>
      <pubDate>Sun, 19 Nov 2017 19:18:54 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414678#M101614</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2017-11-19T19:18:54Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414879#M101691</link>
      <description>&lt;P&gt;Thanks again for the help.&lt;/P&gt;&lt;P&gt;As for your remarks:&lt;/P&gt;&lt;OL&gt;&lt;LI&gt;I'm using the proc sort because the first data step used to merge the open time places the opentime observation as the first row whereas according to its timestamp (09:00:11) it should be in the middle.&lt;/LI&gt;&lt;LI&gt;In your reply, you mentioned "&lt;SPAN&gt;you can do that selection in the first data step" - how?&lt;BR /&gt;I didn't succeed doing that (I can do it using proc sql).&lt;/SPAN&gt;&lt;/LI&gt;&lt;LI&gt;The code for "filling the holes" got different results than I expected, I would greatly appreciate it if you can elaborate.&amp;nbsp;&lt;/LI&gt;&lt;/OL&gt;&lt;P&gt;Here are the results I'm looking for (the red rows are the "holes" I filled manually):&lt;/P&gt;&lt;TABLE&gt;&lt;TBODY&gt;&lt;TR&gt;&lt;TD&gt;TimeStamp&lt;/TD&gt;&lt;TD&gt;X&lt;/TD&gt;&lt;TD&gt;OpenFlag&lt;/TD&gt;&lt;TD&gt;opentime&lt;/TD&gt;&lt;TD&gt;fixed_time&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:01&lt;/TD&gt;&lt;TD&gt;98&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:01&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:03&lt;/TD&gt;&lt;TD&gt;93&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:03&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:04&lt;/TD&gt;&lt;TD&gt;83&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:05&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:04&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;83&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;0&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:11&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:07&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:04&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;83&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;0&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:11&lt;/FONT&gt;&lt;/TD&gt;&lt;TD&gt;&lt;FONT color="#FF0000"&gt;09:00:09&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;62&lt;/TD&gt;&lt;TD&gt;1&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:13&lt;/TD&gt;&lt;TD&gt;60&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:13&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:15&lt;/TD&gt;&lt;TD&gt;54&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:15&lt;/TD&gt;&lt;/TR&gt;&lt;TR&gt;&lt;TD&gt;09:00:16&lt;/TD&gt;&lt;TD&gt;29&lt;/TD&gt;&lt;TD&gt;0&lt;/TD&gt;&lt;TD&gt;09:00:11&lt;/TD&gt;&lt;TD&gt;09:00:17&lt;/TD&gt;&lt;/TR&gt;&lt;/TBODY&gt;&lt;/TABLE&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;Thanks again,&amp;nbsp;&lt;/P&gt;&lt;P&gt;SK&lt;/P&gt;</description>
      <pubDate>Mon, 20 Nov 2017 16:09:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/414879#M101691</guid>
      <dc:creator>SK12376574</dc:creator>
      <dc:date>2017-11-20T16:09:19Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/415024#M101751</link>
      <description>&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;HR /&gt;&lt;a href="https://communities.sas.com/t5/user/viewprofilepage/user-id/175335"&gt;@SK12376574&lt;/a&gt; wrote:&lt;BR /&gt;
&lt;P&gt;Thanks again for the help.&lt;/P&gt;
&lt;P&gt;As for your remarks:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;I'm using the proc sort because the first data step used to merge the open time places the opentime observation as the first row whereas according to its timestamp (09:00:11) it should be in the middle.&lt;/LI&gt;
&lt;LI&gt;In your reply, you mentioned "&lt;SPAN&gt;you can do that selection in the first data step" - how?&lt;BR /&gt;I didn't succeed doing that (I can do it using proc sql).&lt;/SPAN&gt;&lt;/LI&gt;
&lt;LI&gt;The code for "filling the holes" got different results than I expected, I would greatly appreciate it if you can elaborate.&amp;nbsp;&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Here are the results I'm looking for (the red rows are the "holes" I filled manually):&lt;/P&gt;
&lt;TABLE&gt;
&lt;TBODY&gt;
&lt;TR&gt;
&lt;TD&gt;TimeStamp&lt;/TD&gt;
&lt;TD&gt;X&lt;/TD&gt;
&lt;TD&gt;OpenFlag&lt;/TD&gt;
&lt;TD&gt;opentime&lt;/TD&gt;
&lt;TD&gt;fixed_time&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:01&lt;/TD&gt;
&lt;TD&gt;98&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:01&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:03&lt;/TD&gt;
&lt;TD&gt;93&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:03&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:04&lt;/TD&gt;
&lt;TD&gt;83&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:05&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:04&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;83&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;0&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:11&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:07&lt;/FONT&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:04&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;83&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;0&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:11&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD&gt;&lt;FONT color="#ff0000"&gt;09:00:09&lt;/FONT&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;62&lt;/TD&gt;
&lt;TD&gt;1&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:13&lt;/TD&gt;
&lt;TD&gt;60&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:13&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:15&lt;/TD&gt;
&lt;TD&gt;54&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:15&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
&lt;TD&gt;09:00:16&lt;/TD&gt;
&lt;TD&gt;29&lt;/TD&gt;
&lt;TD&gt;0&lt;/TD&gt;
&lt;TD&gt;09:00:11&lt;/TD&gt;
&lt;TD&gt;09:00:17&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TBODY&gt;
&lt;/TABLE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Thanks again,&amp;nbsp;&lt;/P&gt;
&lt;P&gt;SK&lt;/P&gt;
&lt;HR /&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;As to your first comment: if you want&amp;nbsp; a copy of the openflag record in it's proper order, then drop&amp;nbsp; the second "&lt;EM&gt;&lt;STRONG&gt;where=&lt;/STRONG&gt;&lt;/EM&gt;" parameter.&amp;nbsp; I.e. change&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="token procnames"&gt;data&lt;/SPAN&gt; want&lt;SPAN class="token punctuation"&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp; &lt;SPAN class="token keyword"&gt;set&lt;/SPAN&gt; trades &lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;&lt;SPAN class="token statement"&gt;where&lt;/SPAN&gt;&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;openflag&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token number"&gt;1&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; trades &lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;&lt;SPAN class="token statement"&gt;where&lt;/SPAN&gt;&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;openflag&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token number"&gt;0&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp; &lt;SPAN class="token comment"&gt;/*by ticker;*/&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="token comment"&gt;to&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;SPAN class="token comment"&gt;&lt;SPAN class="token procnames"&gt;data&lt;/SPAN&gt; want&lt;SPAN class="token punctuation"&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp; &lt;SPAN class="token keyword"&gt;set&lt;/SPAN&gt; trades &lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;&lt;SPAN class="token statement"&gt;where&lt;/SPAN&gt;&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;(&lt;/SPAN&gt;openflag&lt;SPAN class="token operator"&gt;=&lt;/SPAN&gt;&lt;SPAN class="token number"&gt;1&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;SPAN class="token punctuation"&gt;)&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; trades &lt;SPAN class="token punctuation"&gt;;&lt;/SPAN&gt;&lt;BR /&gt;&amp;nbsp; /*by ticker;*/&lt;/SPAN&gt;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;This allows the openflag=1 record to be read twice: once at the beginning (to&amp;nbsp;extablish opentime)&amp;nbsp;and a second time in chronological order, to provide other data for that trade.&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;More generally, this is a one-step program:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;PRE&gt;&lt;CODE class=" language-sas"&gt;data Trades;
  input TimeStamp time9. X OpenFlag;
  Format TimeStamp time9.;
datalines;
09:00:00 61 0
09:00:01 98 0
09:00:02 54 0
09:00:03 93 0
09:00:04 83 0
09:00:10 42 0
09:00:11 62 1
09:00:12 46 0
09:00:13 60 0
09:00:14 92 0
09:00:15 54 0
09:00:16 29 0
;
run;

data want (drop=nxt_:  _:);
  /* Read the openflag trade, followed by all trades (include 2nd read of openflag trade*/
  set trades (where=(openflag=1) in=optrade)
      trades (in=alltrades)  
      end=end_of_tr;
  /*by ticker; */

  if optrade then do;  /* if optrade set opentime and delete this record ... it will be read again*/
    opentime=timestamp;
    fixed_opentime=round(1+opentime,2);
    _open_minus_60=fixed_opentime-60;    /*Minimum acceptable fixed_time*/
    _open_plus_60=fixed_opentime+60;     /*Maximum acceptable fixed_time*/
    delete;
  end;
  retain opentime fixed_opentime _open_minus_60 _open_plus_60;
  format opentime fixed_opentime _open_minus_60 _open_plus_60 time8.0;

  /* Read ahead one record to get next fixed_time*/
  if end_of_tr=0 then set trades (firstobs=2 keep=timestamp rename=(timestamp=nxt_timestamp));
  else nxt_timestamp=_open_plus_60+2;

  fixed_time=round(1+timestamp,2);
  nxt_fixed_time=round(1+nxt_timestamp,2);
  format fixed_time nxt_fixed_time time8.0;

  if nxt_fixed_time=fixed_time then delete;     /*keep only final rec for each fixed_time*/
  if nxt_fixed_time&amp;lt;_open_minus_60 then delete; /*drop records that are too early*/

  if fixed_time&amp;gt;_open_plus_60 then stop; /*replace "stop" by "delete" if sorted by ticker/timestamp */

  do fixed_time=max(fixed_time,_open_minus_60) to min(nxt_fixed_time-2,_open_plus_60) by 2;
    output;
  end;
run;&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;If the data set has multiple tickers, (i.e.&amp;nbsp;sorted by ticker/timestamp instead of just timestamp), then you should do 2 things:&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;&amp;nbsp;Uncomment the &lt;EM&gt;&lt;STRONG&gt;/*by ticker;*/&lt;/STRONG&gt;&lt;/EM&gt; statement&lt;/LI&gt;
&lt;LI&gt;Change "stop" to&amp;nbsp; "delete" in the "i&lt;EM&gt;&lt;STRONG&gt;f fixed_time&amp;gt;_open_plus_60 then stop;&lt;/STRONG&gt;&lt;/EM&gt;" statement.&lt;/LI&gt;
&lt;/OL&gt;</description>
      <pubDate>Tue, 21 Nov 2017 04:55:13 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/415024#M101751</guid>
      <dc:creator>mkeintz</dc:creator>
      <dc:date>2017-11-21T04:55:13Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/416899#M102384</link>
      <description>&lt;P&gt;I apologize for the delayed response - I fell ill.&lt;/P&gt;&lt;P&gt;Thanks for the complete solution, I highly appreciate it.&lt;/P&gt;&lt;P&gt;SK&lt;/P&gt;</description>
      <pubDate>Tue, 28 Nov 2017 21:55:19 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/416899#M102384</guid>
      <dc:creator>SK12376574</dc:creator>
      <dc:date>2017-11-28T21:55:19Z</dc:date>
    </item>
    <item>
      <title>Re: Converting irregular time-series observations to periodical observations?</title>
      <link>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/416906#M102389</link>
      <description>&lt;P&gt;Sorry for the hassle, but I just notice the solution gives the wrong fixed_time (every 2 seconds relative to 09:12 instead of 09:11).&lt;/P&gt;&lt;P&gt;I changed the code a bit by subtracting 1 from the fixed_time and fixed_opentime variables (I haven't yet fully understand how the code works), so it seems to give the required result:&lt;/P&gt;&lt;P&gt;Thanks again,&amp;nbsp;&lt;/P&gt;&lt;P&gt;SK&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;P&gt;data want (drop=nxt_: _: fixed_opentime);&lt;BR /&gt;/* Read the openflag trade, followed by all trades (include 2nd read of openflag trade*/&lt;BR /&gt;set trades (where=(openflag=1) in=optrade)&lt;BR /&gt;trades (in=alltrades)&lt;BR /&gt;end=end_of_tr;&lt;BR /&gt;/*by ticker; */&lt;/P&gt;&lt;P&gt;if optrade then do; /* if optrade set opentime and delete this record ... it will be read again*/&lt;BR /&gt;opentime=timestamp;&lt;BR /&gt;fixed_opentime=round(1+opentime,2)-1;&lt;BR /&gt;_open_minus_60=fixed_opentime-60; /*Minimum acceptable fixed_time*/&lt;BR /&gt;_open_plus_60=fixed_opentime+60; /*Maximum acceptable fixed_time*/&lt;BR /&gt;delete;&lt;BR /&gt;end;&lt;BR /&gt;retain opentime fixed_opentime _open_minus_60 _open_plus_60;&lt;BR /&gt;format opentime fixed_opentime _open_minus_60 _open_plus_60 time8.0;&lt;/P&gt;&lt;P&gt;/* Read ahead one record to get next fixed_time*/&lt;BR /&gt;if end_of_tr=0 then set trades (firstobs=2 keep=timestamp rename=(timestamp=nxt_timestamp));&lt;BR /&gt;else nxt_timestamp=_open_plus_60+2;&lt;/P&gt;&lt;P&gt;fixed_time=round(1+timestamp,2)-1;&lt;BR /&gt;nxt_fixed_time=round(1+nxt_timestamp,2);&lt;BR /&gt;format fixed_time nxt_fixed_time time8.0;&lt;/P&gt;&lt;P&gt;if nxt_fixed_time=fixed_time then delete; /*keep only final rec for each fixed_time*/&lt;BR /&gt;if nxt_fixed_time&amp;lt;_open_minus_60 then delete; /*drop records that are too early*/&lt;/P&gt;&lt;P&gt;if fixed_time&amp;gt;_open_plus_60 then stop; /*replace "stop" by "delete" if sorted by ticker/timestamp */&lt;/P&gt;&lt;P&gt;do fixed_time=max(fixed_time,_open_minus_60) to min(nxt_fixed_time-2,_open_plus_60) by 2;&lt;BR /&gt;output;&lt;BR /&gt;end;&lt;BR /&gt;run;&lt;/P&gt;&lt;P&gt;&amp;nbsp;&lt;/P&gt;</description>
      <pubDate>Tue, 28 Nov 2017 22:36:05 GMT</pubDate>
      <guid>https://communities.sas.com/t5/SAS-Programming/Converting-irregular-time-series-observations-to-periodical/m-p/416906#M102389</guid>
      <dc:creator>SK12376574</dc:creator>
      <dc:date>2017-11-28T22:36:05Z</dc:date>
    </item>
  </channel>
</rss>

