【问题标题】:Delete observations a certain time period apart删除间隔一定时间段的观察
【发布时间】:2014-06-23 15:15:08
【问题描述】:

所以我有一个数据集,其中包含股票 ID 和 date_time 变量等。我想从下一个 date_time 删除 date_time 变量为 30 分钟且库存相同的所有观察值。因此,如果我的数据集如下所示:

Date_Time|Stock_ID 
01APR11: 07:50:00|Treasury
01APR11: 07:51:00|Treasury

这两个观察结果将被删除。到目前为止,我正在尝试使用 dif 和 lag 函数将它们标记为删除。这是我的代码

data 3;
set 2; 
time_diff=dif(Date_Time)/60; 
same_stock=lag(Stock); 
delete=.;
if abs(time_diff)<=30 AND same_stock=Stock_ID then delete=1;
run;

在这一点之后,我可以删除删除 = 1 的所有观察结果。 问题是,我认为这段代码效率不高,而且肯定容易出错,特别是如果三个日期时间都紧挨着的话。

必须有更好的方法来做到这一点。

【问题讨论】:

  • 您希望如何处理跨度大于 60 分钟的同一股票的一系列条目,但所有条目之间的间隔都小于 10 分钟?全部删除?
  • 是的,我想全部删除。
  • 老实说,我不认为您现有的方法太糟糕,除非您的数据集非常庞大并且您迫切希望避免多次阅读它。数据集是否按任何特定顺序排序?
  • 是的,所以它首先按股票 ID 排序,然后按时间排序,这就是我的解决方案可以工作的原因。这非常令人担忧,因为我认为它很容易出错。

标签: datetime sas time-series


【解决方案1】:

我想出了一种我认为可行的方法。它添加了以下代码:

proc expand data=3 out=4 method=none; 
convert delete=delete_lead1 / transformout=(lead 1); 
run; 

现在这给了我一个数据集,其中包含我第一步中的删除变量和一个前导变量 (delete_lead1),它将为我需要删除的另一行提供一个值。我检查了所有观察结果,它甚至适用于 4 或 5 行,所以我对这个解决方案更有信心。

【讨论】:

    【解决方案2】:

    我想说原始解决方案的危险之处在于它是 不按时间顺序读取股票记录,因此删除可能会受到源数据中记录顺序的影响。

    我建议: 1)按时间顺序在数据步中处理 2)如果你的表现很关键,我只输出最终记录(一旦逻辑正确)

    顺便说一句,我想知道你真的使用数字作为表名。

    /* sort data */
    proc sort data=d2;
    by stock Date_Time;
    run;
    
    /* or create index */
    proc sql;
    create index idx1 on d2 (stock Date_Time);
    quit;
    
    /* or create view and use V2 instead of D2 */
    proc sql;
    create view V2 as select * from D2 order by stock Date_Time;
    quit;
    
    data d3;
    set d2 /* or use V2 if created the view */;
    by stock Date_Time;
        if first.stock = 1 then output;/* first row always kept for the stock */
        else do;
            time_diff=dif(Date_Time)/60; 
            if time_diff > 30 then output;
        end;
    run;
    

    已更新(未尝试)以删除距离上次保存记录不到 30 秒的所有记录:

    data d3;
    set d2 /* or use V2 if created the view */;
    retain last_kept_dt;
    by stock Date_Time;
        if first.stock = 1 then do;
            last_kept_dt = Date_Time;
            output;/* first row always kept for the stock */
        end;
        else do;
            time_diff = (Date_Time - last_kept_dt)/60;
            if time_diff > 30 then do;
                 output;
                 last_kept_dt = Date_Time;
              end;
        end;
    run;
    

    【讨论】:

    • 我实际上并没有使用数字作为表名...仅作为示例!谢谢你的帮助。我想删除相隔 30 分钟的所有行,而不仅仅是其中之一……你知道这是否可能吗?例如,如果我有两只间隔 25 分钟交易的股票,我想删除它们。
    • 我收到一个错误,指出 do 循环没有正确关闭。我尝试修复结束语句,但它没有工作......同样的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多