了解SAS上表格上的开始日期和最新日期

了解SAS上表格上的开始日期和最新日期,sas,Sas,我是一名非常新的学生,因此对SAS的世界非常熟悉,虽然我去年在学习期间使用过SAS,但理论知识与实际操作知识不同 这是我的问题 我有SAS上的表,如下例所示: table1 date var_1 var_2 var_3 var_4 var_5 1957M1 . . . . . 1957M2 . . . . 23.5 1957M3 . 1.2 .

我是一名非常新的学生,因此对SAS的世界非常熟悉,虽然我去年在学习期间使用过SAS,但理论知识与实际操作知识不同

这是我的问题

我有SAS上的表,如下例所示:

table1

date    var_1   var_2   var_3   var_4   var_5
1957M1   .       .      .       .       .
1957M2   .       .      .       .       23.5
1957M3   .       1.2    .       .       23.6
1957M4   .       1.3    .       .       23.7
1957M5   .       1.4    .       0.123   23.8
1957M6   .       1.5    .       0.124   23.9
1957M7   .       1.6    3.0     0.125   23.10
1957M8   .       1.7    3.1     0.126   23.11
1957M9   .       1.8    3.2     0.127   23.12
1957M10  2.1     1.9    3.3     0.128   23.13
1957M11  2.2     1.10   3.4     0.129   23.14
1957M12  2.3     1.11   3.5     0.130   23.15
正如您所猜测的,每个变量本身就是一个时间序列,日期也是一个时间序列。列是数字列,日期列除外,日期列是字符列

我的目标是了解每个变量的开始日期和最新日期

var_1将于1957年10月(或M10)开始,最晚的日期是1957年12月(或M12)

var_4将于1957年10月(或M10)开始,最晚日期为12月(或M12)

我已经通过SAS对一列一表进行了以下测试,但这需要很长时间,没有结果

PROC SQL NOPRINT;
SELECT 
    MIN(input(substr(date,1,4),date4.)),
    MAX(input(substr(date,1,4),date4.))
FROM
table1
WHERE 
var_2 <> "."
quit;
procsqlnoprint;
挑选
最小值(输入(子字符串(日期,1,4),日期4.),
最大值(输入(substr(日期,1,4),日期4.))
从…起
表1
哪里
变量2“
退出
对于我的查询,日期列是文本。我正在尝试通过我的查询将其转换为只包含年份的日期格式,尽管我将只包含年份,拥有月份会很好

我的老板告诉我关于
PROC-FREQ
以实现我想要的结果,但我不知道如何实现

如果你有任何线索,我就要了


干杯。

您的问题是您的数据结构并不适合您的问题

正确的数据结构是更垂直的结构,包含日期、VAR和值。然后
PROC意味着
非常适合您的需要

data have;
input date $    var_1   var_2   var_3   var_4   var_5;
datalines;
1957M1   .       .      .       .       .
1957M2   .       .      .       .       23.5
1957M3   .       1.2    .       .       23.6
1957M4   .       1.3    .       .       23.7
1957M5   .       1.4    .       0.123   23.8
1957M6   .       1.5    .       0.124   23.9
1957M7   .       1.6    3.0     0.125   23.10
1957M8   .       1.7    3.1     0.126   23.11
1957M9   .       1.8    3.2     0.127   23.12
1957M10  2.1     1.9    3.3     0.128   23.13
1957M11  2.2     1.10   3.4     0.129   23.14
1957M12  2.3     1.11   3.5     0.130   23.15
;;;; 
run;

data want;
set have;
array var_[5];
date_num = mdy(substr(date,6),1,substr(date,1,4));
do _iter= 1 to dim(var_);
  if not missing(var_[_iter]) then do;
   var = vname(var_[_iter]);
   value = var_[_iter];
   output;
  end;
end;
format date_num MONYY.;
run;

proc means data=want;
class var;
var date_num;
output out=edge_dates min= max= /autoname;
run;

如果性能有问题,这是我知道的最快的方法,因为它只需要读取一次数据。使用Joe的代码创建“have”数据集:

data want;
  format date_num start1-start5 end1-end5 monyy.;

  set have end=eof;
  retain start1-start5 end1-end5 .;                  * RETAIN THE VALUES WE WILL BE CALCULATING AS WE ITERATE ACROSS ROWS IN THE DATASET;

  array arr_var  [*] var_1-var_5  ;                  * ARRAY FOR EXISTING VARIABLES;
  array arr_start[*] start1-start5;                  * ARRAY FOR NEW VARIABLES THAT WILL CONTAIN START DATE;
  array arr_end  [*] end1-end5    ;                  * ARRAY FOR NEW VARIABLES THAT WILL CONTAIN END DATE;

  date_num = mdy(input(substr(date,6),best.),1,input(substr(date,1,4),best.));

  do iter=1 to dim(arr_var);                         * LOOPING FOR THE NUMBER OF VARIABLES IN ARR_VAR;
    if arr_var[iter] ne . then do;                   * ONLY GOING TO PERFORM CALCS WHEN THE VARIABLE IS NOT MISSING;

      if arr_start[iter] eq . then do;
       arr_start[iter] = date_num;                   * ONLY UPDATE THE START DATE IF IT HASNT ALREADY BEEN SET;
      end;
      arr_end[iter] = date_num;                      * IF ITS NOT MISSING, ALWAYS UPDATE THE END DATE;

    end;
  end;

  if eof then do;
    output;                                          * ONLY OUTPUT THE CALCULATED VALUES ONCE WE HIT THE END OF THE DATASET;
  end;

  keep start: end:;                                  * KEEP ONLY VARS STARTING WITH START OR END;
run;
通常我不建议这样计算开始日期和结束日期,除非性能是一个考虑因素,或者如果这段代码最终比其他代码更简单


大多数情况下,您最好以不同的方式准备数据结构,尽管在某些情况下,使用上述格式的数据也是有利的

仅供参考,我怀疑
PROC-FREQ
解决方案基本上与我下面的解决方案做了相同的事情-通过PROC-FREQ将其转换为垂直表。嗨,乔,谢谢你的回答。然而,我有一个问题。这是进行转置的唯一方法吗?这当然不是唯一的方法,但这是一个非常好的方法。几乎任何其他方式都需要分别为每个var编码。问题是,从某种意义上说,你的数据与你的数据相差90度(无论如何,对于这个问题)。好吧,就像我说的,你可以使用PROC FREQ做与我上面做的基本相同的事情-这很容易做到。我不确定哪个更快;我倾向于使用数据步骤,因为它更清楚你在做什么,但是PROC-FREQ可能会快一点。这段代码对我来说毫无意义。我认为它基本上是在做我的代码正在做的事情,但是还有很多步骤。这些数据步骤中的大多数都是无用的。这是一个宏编程的好例子,你不应该使用宏编程。我会的。真的有那么糟糕。嗨,罗伯特,为解决方案干杯。最好的,