我是一名新的SAS用户,我遇到了一个小问题
我有一个大的空表A,可以说我用简单proc sql; create table
我有另一个表B,让我们说40列,表C有55列。 我想将这两个表添加到表A中,基本上我想要一个包含100列的表,其中包含表B和表中的数据。 C和我用联盟命令做这件事。
由于我没有所有100个变量的值,我必须设置默认值。 假设我在表A中有一个名为nourishment的列,表B中的食物在表C中没有等效。我有类似&#34的规则;如果数据来自表B,则值= xxx,如果它来自表C然后值="默认值"
我可以用R或python轻松做到这一点,但我正在与sas挣扎。
我使用SAS sql命令(Union命令)
如何设置默认值? (对于所有数据类型:字符,数字或日期使用SAS sql命令)
答案 0 :(得分:1)
SAS中的日期实际上只是数值。他们通常会使用日期格式来使其可读。
所以你可以默认分配一个缺失的值,如下所示:
. as ColumnName
或任何默认日期
'17NOV2017'd as ColumnName
答案 1 :(得分:0)
. as MyColumnName
SAS可以处理缺失值。
使用特殊编码的值(例如“NA'”来表示缺失值条件可以起作用,但可能导致头痛和额外编码。推荐阅读SAS帮助:"使用缺失值"
数字的默认SAS缺失值(也包括日期)是句点。
. as MyColumnName
SAS还有27个特殊的数字缺失值,表示为。 <字符>
.A as MyColumnName
...
.Z as MyColumnName
._ as MyColumnName
字符变量的缺失值是单个空格
' '
'' empty quote string also works
' ' as does a longer empty string
经验法则:在编写缺失值时保持一致。
您可以使用OPTIONS MISSING指定打印缺失值时显示的字符。
OPTIONS MISSING = '*'; * My special representation of missing for this report;
Proc PRINT data=myData;
run;
OPTIONS MISSING = '.'; * Restore to the default;
SAS自定义格式还可用于自定义缺失值的打印内容。
Proc FORMAT;
value MissingN
. = 'N/A'
.N = 'Special N/A different than regular N/A' /* for .N */
;
value $MissingC
' ' = 'N/A'
;
value SillyChristmasStocking
.C = 'Bad'
.O = 'children'
.A = 'get'
.L = 'No toys'
;
value
关键字后面的令牌可以是您要用于格式名称的任何新的有效SAS名称。
Proc PRINT data=myData;
format myColumnName MissingN.;
format name $MissingC.;
format behaviour SillyChristmasStocking.;
run;
至于您的角色缺失值条件,我会继续使用" "
或' '
你提到UNION这是一个SQL功能。在SQL中,JOIN也可能发生,也许更常见于UNION。当JOINing和来自两个源列的值发生冲突时,您将需要使用COALESCE()函数或CASE 用于选择非缺失值的语句。
答案 2 :(得分:0)
我不建议您在SAS使用的任何时候在UNION
中使用PROC SQL
。 UNION
几乎总是不如简单的数据步骤或数据步骤视图。
这是因为数据步骤无缝地处理不同表上的不同变量等问题。 SAS非常适合垂直组合数据集;当它们不相同时,SQL总是有点棘手。
data c;
set a b;
run;
只要a
和b
没有冲突的变量名,a
和b
是否相同就会运行(不打算在同一列中);如果他们这样做,只需使用rename
数据集选项来解决它。
如果您按上述方式操作,并且不使用union
,则会自动为这些日期获取缺失值。
答案 3 :(得分:0)
NFN:
用于堆叠数据的数据步骤方法是最简单的。使用SET堆叠数据和数组处理以应用默认值。例如:
data stacked_data;
set
TARGET_TEMPLATE (obs = 0)
ONE
TWO
;
array allchar _character_;
array allnum _numeric_;
array dates d1-d5;
do over allchar; if missing(allchar) then allchar = '*UNKNOWN*'; end;
do over allnum; if missing(allnum) then allnum = -995; end;
do over dates; if missing(dates) then dates='01NOV1971'd; end;
run;
一个微妙的问题是ONE或TWO中的任何缺失值都将替换为默认值。
在Proc SQL中,您需要创建一个包含A的默认值的单行表。该表可以连接到B和C的并集。连接选择将涉及coalesce()以选择预定义的默认值当列不是来自B或C时的值。
例如,假设您有一个空的(零行),丰富的圆柱,目标表(您的A)充当模板:
data TARGET_TEMPLATE;
length _n_ 8;
length a1-a5 $25 d1-d5 4 x1-x20 y1-y20 z1-z20 p1-p20 q1-q20 r1-r20 8;
call missing (of _all_);
format d1-d5 yymmdd10.;
stop;
run;
由于Proc SQL不提供默认约束的语法,因此您需要创建自己的默认值的表。这可能是最简单的DATA步骤:
data TARGET_DEFAULTS;
if 0 then set TARGET_TEMPLATE (obs=0); * prep pdv to match TARGET;
array allchar _character_ (1000 * '*UNKNOWN*');
array allnum _numeric_ (1000 * -995);
array d d1-d5 (5 * '01NOV1971'd); * override the allnum array initialization;
output;
stop;
run;
以下是一些生成的演示数据,ONE和TWO,对应于您的B和C:
data ONE;
if 0 then set TARGET_TEMPLATE (obs=0); * prep pdv of demo data to match TARGET;
do _n_ = 1 to 100;
array a a1 a3 a5;
array num x: y: z:;
array d d1 d2;
do over a; a = catx (' ', 'ONE', _n_, _i_); end;
do over num; num = 1000 + _n_ + _i_; end;
retain foodate '01jan1975'd;
do over d; d=foodate; foodate+1; end;
output;
end;
keep a1 a3 a5 x: y: z: d1 d2; * keep the disparate columns that were populated;
run;
data TWO;
if 0 then set TARGET_TEMPLATE (obs=0); * prep pdv of demo data to match TARGET;
do _n_ = 1 to 200;
array a a1 a2 a3;
array num x5 y5 z5 p: q: r:;
array d d1 d2;
do over a; a = catx (' ', 'TWO', _n_, _i_); end;
do over num; num = 20000 + _n_*10 + _i_; end;
retain foodate '01jan1985'd;
do over d; d=foodate; foodate+1; end;
output;
end;
keep a1 a2 a3 x5 y5 z5 p: q: r:; * keep the disparate columns that were populated;
run;
A,B和C的堆叠是简单的SQL,但不会引入目标特定的默认值:
proc sql noprint;
* generic UNION stack with SAS missing values (space and dot) for cells
* where ONE and TWO did not contribute any data;
create table stacked_data as
select * from have_data_TEMPLATE %*** empty template first ensures template column order and formats are honored in output data;
outer union corresponding %*** align by column name, do not remove duplicates;
select * from ONE
outer union corresponding
select * from TWO
;
当堆叠放在子查询中时,它可以与默认值连接。为每列选择目标默认值包括检查DICTIONARY.COLUMNS并生成用于选择堆栈和默认值的合并的SQL源。
proc sql noprint;
* codegen select items ;
select cat('coalesce(STACK.',trim(name),',DEFAULT.',trim(name),') as ',trim(name))
into :coalesces separated by ','
from DICTIONARY.COLUMNS
where libname = 'WORK' and memname = 'HAVE_DATA_TEMPLATE' %* dictionary lib and mem name values are always uppercase;
order by npos
;
create table stacked_data_with_defaults as
select * from TARGET_TEMPLATE %*** output honors template;
outer union corresponding
select
source
, &coalesces %*** apply codegen;
from
(
select * from WORK.have_data_TEMPLATE %*** ensure fully columned sub-select that will align with coalesces;
outer union corresponding
select 'one' as source, * from ONE
outer union corresponding
select 'two' as source, * from TWO
) as STACK
join
TARGET_DEFAULTS as DEFAULT
on 1=1
;
quit;
答案 4 :(得分:0)
为什么要创建一个空数据集?它将被用于什么?也许您想将它用作默认结构定义?如果是这样,你想要堆叠B和C并将它们放在A定义的结构中,你可以用这种方式编码。
data want ;
set a(obs=0) b c ;
run;
不确定具有默认值的目的是什么。如果您希望以特殊方式显示缺失值,则无法使用格式吗?
或者您可以创建默认值的代码,也许只是包含它或将逻辑包装到宏中。所以你有一个代码文件名' defaults.sas'用这样的线条。
startdate=coalesce(startdate,'01JAN2013'd);
gender=coalescec(gender,'UNKNOWN');
然后你的小程序制作一个看起来像A的新数据集并使用B和C中的数据看起来像这样。
data want ;
set a(obs=0) b c ;
%include 'defaults.sas';
run;
如果您确实想要将记录聚合到某个大型数据集中,那么您可能希望在正确的结构中创建记录后使用PROC APPEND
添加记录。
proc append data=want base=a ;
run;