代码之家  ›  专栏  ›  技术社区  ›  Konrad

强制proc export为不存在的变量创建空白列

  •  0
  • Konrad  · 技术社区  · 7 年前

    出身背景

    我正在运行下面的宏来导出循环中的许多数据集。不幸的是,其中一些数据集有额外的变量。我的目的是以相同的格式导出所有文件,其中 不存在的列作为空白提供 .

    数据

    这可以用以下数据集来说明。

    dataA

    varA varB
    1    3
    2    3
    3    3
    

    dataB

    varA varB
    9    4
    9    4
    9    4
    

    dataC

    varA varB varC
    2    5    6
    2    5    6
    2    5    6
    

    我希望我的CSV文件如下所示:

    dataA.CSV

    varA varB varC
    1    3    .
    2    3    .
    3    3    .
    

    dataB.CSV

    varA varB varC
    9    4    .
    9    4    .
    9    4    .
    

    dataC.CSV

    varA varB varC
    2    5    6
    2    5    6
    2    5    6
    

    %macro export_data(dsnms);
        * Get observations count;
        PROC SQL;
            SELECT COUNT(*) INTO :obscount
                FROM &dsnms;
        QUIT;
    
        * Export all available files in the loop;
        %Local D;
    
        %DO D = 1 %TO &obscount;
    
            * Print progress message;
            sysecho "Progressing through &D of &obscount";
    
            * Get table name;
            PROC SQL;
                SELECT COMPRESS(MEMNAME) INTO: Table
                    FROM &dsnms
                        WHERE rownum=&D;
            QUIT;
    
            * Extra spaces in file name are removed via cmpres call;
            PROC EXPORT DBMS=CSV DATA=SASLIBWITHSTUFF.&Table
                OUTFILE="/mystuff/%cmpres(&Table).csv";
            RUN;
    
            * Inform about succesful export;
            sysecho "Created &Table..csv export file.";
        %END;
    %mend;
    

    总结

    换句话说,我想修改 proc export 创建 NonExistingVar 如果在 Kepp = . 当然,这将失败 sashelp.class 没有 不存在VaR 但这是我想效仿的行为。

    proc export data=sashelp.class (keep =  name
                                            sex
                                            NonExistingVar)
       outfile="/stuff/proc_test.csv"
       dbms=csv
       replace;
    run;
    
    2 回复  |  直到 7 年前
        1
  •  2
  •   user667489    7 年前

    如果您在某个位置有一个宏变量,其中包含要导出的列的列表,则可以构建一个包含这些列的视图,包括基础数据集中不存在的列,然后导出该视图。例如。

    %let keepcols = sex weight newcol;
    
    data t_view /view = t_view;
      if 0 then set sashelp.class; 
      if _n_ = 1 then call missing(of &keepcols);
      set sashelp.class;
    run;
    

    这个 if 0 then set xyz 是一个很好的小技巧,它允许您保留列顺序、长度和类型,而不必从第一个set语句中读取任何行。当随后将变量设置为缺失值时,它避免了冲突类型-我们必须将它们初始化为 某物 否则,它们不会输出。然后,第二个set语句将覆盖实际存在的变量缺少的值。

    如果查询元数据表以确定保留的列中存在哪些列,那么这可能会更加有效,因此只加载这些列,但对于大多数情况来说,这应该是合理的。

    更懒惰的选项是暂时禁用保留相关的错误和警告,例如:

    %let keepcols = sex weight newcol;
    
    %let dkricond = %sysfunc(getoption(dkricond)); /*Save for later*/
    option dkricond = nowarn;
    
    data t_view /view = t_view;
      if 0 then set sashelp.class(keep = &keepcols); /*Normally this would trigger an error or warning*/
      retain &keepcols;
      set sashelp.class(keep = &keepcols); 
    run;
    
    option dkricond = &dkricond; /*Restore original setting*/
    
        2
  •  0
  •   Tom    7 年前

    要实现这一点,您需要有一个要输出的变量列表。所以,让我们假设您有一个宏变量和该列表。

    %let varlist=varA varB varC ;
    

    由于您正在编写CSV文件,因此只需直接使用数据步骤即可,并且避免使用PROC EXPORT。在数据步骤中,如果您引用了一个不存在的变量,那么SAS会很乐意为您创建一个空变量。

    添加标题记录可能需要一些创造性。这里有一种使用TRANWRD()函数的方法,当每个变量名之间只有一个空格时,该方法就会起作用。注意,您可以使用COMPBL()来实现这一点。

    %let varlist=Name Unknown    Age ;
    %let varlist=%sysfunc(compbl(&varlist));
    
    data _null_;
      file "/stuff/proc_test.csv" dsd ;
      if _n_=1 then put "%sysfunc(tranwrd(&varlist,%str( ),%str(,)))" ;
      set sashelp.class ;
      put &varlist ;
    run;
    

    结果:

    Name,Unknown,Age
    Alfred,,14
    Alice,,13
    Barbara,,13
    Carol,,14
    Henry,,14
    James,,12
    Jane,,12
    Janet,,15
    Jeffrey,,13
    John,,12
    Joyce,,11
    Judy,,14
    Louise,,12
    Mary,,15
    Philip,,16
    Robert,,12
    Ronald,,15
    Thomas,,11
    William,,15