sas 中的第一次和最后一次观察

Posted

技术标签:

【中文标题】sas 中的第一次和最后一次观察【英文标题】:first and last observations in sas 【发布时间】:2016-06-29 18:59:50 【问题描述】:

我正在尝试根据基线日期(在我的数据集中称为baseline_doc)为所有相同的client_id分组标记第一个和最后一个观察结果。

例如,我希望我的最终数据集如下所示:

Client_id    Baseline_Date       First.baseline_doc    Last.baseline_doc 
---------    ------------------  ------------------    -----------------
1            April 1 2016        0                     0
1            April 20 2016       0                     1
1            January 1 2016      1                     0
2            January 1 2016      1                     0
2            January 20 2016     0                     1
3            February 20 2016    1                     1

请注意如何在第一个和最后一个 client_id 的类似分组中为 client_id 的第一个实例和该 client_id 的最后一个实例标记,然后在每个 client_id 分组中第一个和最后一个观察被标记-第一个日期标记为 1 first.baseline_doc 和最后一个日期(或最近的)被标记为 last.baseline_doc 这是我正在使用的代码:

data FA_CA_DADOS_CLEAN_DELETED;
    set fa_ca_dados_clean2;
    by client_id baseline_doc;
    firstclient_id = first.client_id;
    lastclient_id = last.client_id;
    firstBaseline_doc = first.baseline_doc;
    lastBaseline_doc = last.baseline_doc;
run;

但是,我的代码并没有给我想要的输出。发生的事情是每个 client_id 都被标记为 last.baseline_doc 的 1 但肯定有一些应该是 0 b/c 我有不同日期的重复 client_ids。

我做错了什么?

我直接从这个资源中复制了这段代码: https://onlinecourses.science.psu.edu/stat481/node/9

它有我想要的输出,所以我不确定发生了什么。

在运行上面的代码之前,我按 client_id 和 baseline_doc 进行了排序!

有人可以帮帮我吗?

【问题讨论】:

你肯定不明白。 first.something 表示此观察是第一个具有一定something 的观察。如果您将 first.baseline_doc 用于完全不同的概念,您真的会让您的同事感到困惑。 也许您应该首先按 Client_id、Baseline_Date 对输入数据进行排序? 【参考方案1】:

读入数据后
data myData;
    input @01 Client_id 1. 
        @03 Baseline_Doc date9. ;
    format Baseline_Doc yymmdd10.;
    datalines;
1  1Apr2016 0 0
1 20Apr2016 0 1
1  1Jan2016 1 0
2  1Jan2016 1 0
2 20Jan2016 0 1
3 20Feb2016 1 1
;
run;

这样就可以了:

proc sql;
    select all.*
         , case baseline_Doc when baseline_min then 1 else 0 end as baseline_start
         , case baseline_Doc when baseline_max then 1 else 0 end as baseline_stop
    from myData all inner join 
    (   select Client_id
             , min(baseline_doc) as baseline_min
             , max(baseline_doc) as baseline_max
        from myData
        group by Client_id ) as min_max on all.Client_id = min_max.Client_id;
quit;

但是,它可能会带来不愉快的惊喜,因为根据 SQL 的规范,它不必保留顺序。

【讨论】:

【参考方案2】:

如果我理解正确,您想在每个 client_id 中标记最早和最晚的日期。为此,您需要查找 first.client_id 和 last.client_id,而不是 first.baseline_doc 和 last.baseline_doc。将 first.x / last.x 视为等效于“这是当前值为 x 的第一行/最后一行”。

试试这个:

data myData;
    input @01 Client_id 1. 
        @03 Baseline_Doc date9. ;
    format Baseline_Doc yymmdd10.;
    datalines;
1  1Apr2016 0 0
1 20Apr2016 0 1
1  1Jan2016 1 0
2  1Jan2016 1 0
2 20Jan2016 0 1
3 20Feb2016 1 1
;
run;

proc sort data = mydata;
  by client_id baseline_doc;
run;

data want;
  set mydata;
  by client_id;
  first_baseline_doc = first.client_id;
  last_baseline_doc  = last.client_id;
run;

【讨论】:

有了你的答案,你就不会得到想要查看@chiccaboomberry 的结果数据【参考方案3】:

如果您想 100% 确定订单被保留,您可以这样做

按基线日期升序对输入进行排序,但要记住原来的观察号;

data myInput;
   input @01 Client_id 1. 
         @03 Baseline_Doc date9. ;
   format Baseline_Doc yymmdd10.;
   obsNr = _N_;
   datalines;
1  1Apr2016 0 0
1 20Apr2016 0 1
1  1Jan2016 1 0
2  1Jan2016 1 0
2 20Jan2016 0 1
3 20Feb2016 1 1
;
run;
proc sort data = myInput out=myTemp;
  by client_id baseline_doc;
run;

标记第一个和最后一个基线日期;

data myTemp;
  set myTemp;
  by client_id baseline_doc;
  baseline_start = first.client_id;
  baseline_end = last.client_id;
run;

恢复原来的顺序,忘记obsNr;

proc sort data = myTemp out=myResult(drop=obsNr);
  by obsNr;
run;

【讨论】:

【参考方案4】:
data myData;
   input @01 Client_id 1. 
         @03 Baseline_Doc date9. ;
   format Baseline_Doc yymmdd10.;
   datalines;
   1  1Apr2016 0 0
   1 20Apr2016 0 1
   1  1Jan2016 1 0
   2  1Jan2016 1 0
   2 20Jan2016 0 1
   3 20Feb2016 1 1
   ;
run;
proc sort data = mydata;
  by client_id baseline_doc;
run;

data want;
  set mydata baseline_doc;
  by client_id baseline_doc;
  if first.client_id then First.baseline_doc = 1;
  else First.baseline_doc = 0;
  if last.client_id then Last.baseline_doc = 1;
  else Last.baseline_doc = 0;
run;

【讨论】:

这不能回答问题(第一个和最后一个变量总是被丢弃),由于使用了 first.baseline_doc,这很令人困惑,除此之外,它几乎与我的答案完全相同.

以上是关于sas 中的第一次和最后一次观察的主要内容,如果未能解决你的问题,请参考以下文章

在来自多个传感器的定时观察表中,如何以最佳方式检索每个传感器的最后一次观察

R中NA的条件操作

SAS - 如何从数据集中获取最后的“n”个观察结果?

第一次接触sas编程

SAS笔记 FIRST.和LAST.临时变量

如何在PostgreSQL中的字符串中查找特定字符的第一次和最后一次出现