Variables SAS崩溃日期

Variables SAS崩溃日期,variables,sas,collapse,Variables,Sas,Collapse,我有一个如下所示的数据集: cust date 1 2 3... 600 1 1 5 . . ... . 1 2 5 . . ... . 1 2 . 4 . ... . 1 2 . . 6 ... . 2 1 1 . . ... . 2 1 . 5 . ... . 2 2 . . . ... 10 cust date 1 2 3... 600 1 1 5 . . ... . 1 2 5

我有一个如下所示的数据集:

cust date 1 2 3... 600
1    1    5 . . ... .
1    2    5 . . ... .
1    2    . 4 . ... .
1    2    . . 6 ... .
2    1    1 . . ... .
2    1    . 5 . ... .
2    2    . . . ... 10
cust date 1 2 3... 600
1    1    5 . . ... .
1    2    5 4 6 ... .
2    1    1 5 . ... .
2    2    . . . ... 10
我想按客户(cust)将每个日期的变量1折叠到600,以便数据集如下所示:

cust date 1 2 3... 600
1    1    5 . . ... .
1    2    5 . . ... .
1    2    . 4 . ... .
1    2    . . 6 ... .
2    1    1 . . ... .
2    1    . 5 . ... .
2    2    . . . ... 10
cust date 1 2 3... 600
1    1    5 . . ... .
1    2    5 4 6 ... .
2    1    1 5 . ... .
2    2    . . . ... 10
我从以下代码开始(可能有点复杂),但它不起作用:

data want ;
set have;
array vars &list.; *stored array of variables 1-600;
retain count vars;
by cust date;
if first.date then do;
do _i=1 to dim(vars);
vars[_i]=.; 
end;
count=0;
end;
count=count+1;
vars[_1]=vars;
if last.date then do;
output;
end;
drop count;
run;
你知道吗?另一个想法是使用proc expand,但它也不起作用,因为日期是重复的


非常感谢你的帮助

set
语句中,不能将RETAIN与来自数据集的变量一起使用;或者更准确地说,您可以,但它不起作用-变量将
RETAIN
set语句中的变量自动删除。但是,当
集合
发生时,它们也会被数据步骤的下一次迭代所覆盖

您可以使用临时数组存储保留的值,并在
last.date
时将其复制回来(临时数组也会自动保留,仅供参考),也可以使用完全不同的技术—哈希表、SQL,以及您最熟悉的任何技术

比如说,

proc sql;
create table want as 
  select cust, date, sum(var1) as var1, sum(var2) as var2, ... 
  from have
  group by cust,date;
quit;
您可能希望在宏变量中将
sum(var1)构造为var1
,例如

%macro sumvar(var=)
sum(&var.) as &var.
%mend sumvar;
proc sql;
select cats('%sumvar(var=',name,')') 
  into :sumlist separated by ','
  from dictionary.columns
  where libname='WORK' and memname='HAVE' and not (name in ('CUST','DATE'))
;
quit;
然后使用这个&sumlist。在上面的sql中

select cust, date, &sumlist.

这可能是最容易编写的代码;如果您有非常大的数据,那么它可能不如其他选项有效。

您不能在
set
语句中使用RETAIN和来自数据集的变量;或者更准确地说,您可以,但它不起作用-变量将
RETAIN
set语句中的变量自动删除。但是,当
集合
发生时,它们也会被数据步骤的下一次迭代所覆盖

您可以使用临时数组存储保留的值,并在
last.date
时将其复制回来(临时数组也会自动保留,仅供参考),也可以使用完全不同的技术—哈希表、SQL,以及您最熟悉的任何技术

比如说,

proc sql;
create table want as 
  select cust, date, sum(var1) as var1, sum(var2) as var2, ... 
  from have
  group by cust,date;
quit;
您可能希望在宏变量中将
sum(var1)构造为var1
,例如

%macro sumvar(var=)
sum(&var.) as &var.
%mend sumvar;
proc sql;
select cats('%sumvar(var=',name,')') 
  into :sumlist separated by ','
  from dictionary.columns
  where libname='WORK' and memname='HAVE' and not (name in ('CUST','DATE'))
;
quit;
然后使用这个&sumlist。在上面的sql中

select cust, date, &sumlist.

这可能是最容易编写的代码;如果您的数据非常大,它可能不如其他选项有效。

您可以这样做:

proc means data=have noprint;
  by cust date;
  var &list;
  output out=want(drop=_:) sum=;
run;

您可以这样做,如下所示:

proc means data=have noprint;
  by cust date;
  var &list;
  output out=want(drop=_:) sum=;
run;

使用UPDATE语句可以实现这一点。对现有表的第一个引用(obs=0)创建一个具有所需结构的空表,第二个引用使用值更新。BY语句确保每个BY值只输出一条记录。希望这是有意义的

data have;
input cust date v1 v2 v3 v600;
datalines;
1    1    5 . . .
1    2    5 . . .
1    2    . 4 . .
1    2    . . 6 .
2    1    1 . . .
2    1    . 5 . .
2    2    . . . 10
;
run;

data want;
update have (obs=0) have;
by cust date;
run;

使用UPDATE语句可以实现这一点。对现有表的第一个引用(obs=0)创建一个具有所需结构的空表,第二个引用使用值更新。BY语句确保每个BY值只输出一条记录。希望这是有意义的

data have;
input cust date v1 v2 v3 v600;
datalines;
1    1    5 . . .
1    2    5 . . .
1    2    . 4 . .
1    2    . . 6 .
2    1    1 . . .
2    1    . 5 . .
2    2    . . . 10
;
run;

data want;
update have (obs=0) have;
by cust date;
run;

好主意您可能应该将
by
更改为
class
,除非数据保证已排序(以避免排序)。谢谢,我选择by的原因是因为示例数据步骤中有一个by,所以我认为它可能已排序。好主意。您可能应该将
by
更改为
class
,除非数据保证已排序(以避免排序)。谢谢,我选择by的原因是因为示例数据步骤中有一个by,所以我认为它可能已排序。@Joe,至少它不是Pete Best!;-)@基思,非常感谢你!这句话真的很有帮助!很好用@乔,至少这不是皮特最好的!;-)@基思,非常感谢你!这句话真的很有帮助!很好用!!