定义默认值

时间:2017-11-17 11:58:05

标签: sas

我是一名新的SAS用户,我遇到了一个小问题

我有一个大的空表A,可以说我用简单proc sql; create table

创建的100列

我有另一个表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命令)

5 个答案:

答案 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 SQLUNION几乎总是不如简单的数据步骤或数据步骤视图。

这是因为数据步骤无缝地处理不同表上的不同变量等问题。 SAS非常适合垂直组合数据集;当它们不相同时,SQL总是有点棘手。

data c;
  set a b;
run;

只要ab没有冲突的变量名,ab是否相同就会运行(不打算在同一列中);如果他们这样做,只需使用rename数据集选项来解决它。

如果您按上述方式操作,并且不使用union,则会自动为这些日期获取缺失值。

答案 3 :(得分:0)

NFN:

DATA Step

用于堆叠数据的数据步骤方法是最简单的。使用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

在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;