【问题标题】:SAS Macro help to loop monthly sas datasetsSAS 宏帮助循环每月 sas 数据集
【发布时间】:2017-11-13 13:10:58
【问题描述】:

从 2013 年 1 月起,我在 SAS 库中为客户提供每月数据集,数据集名称为 CUST_JAN2013、CUST_FEB2013........CUST_OCT2017。这些客户数据集每月有 200 万会员的巨大记录。这个月度数据集有两列(客户数量和客户每月费用)。

我有一个以客户编号和月份为列的输入数据集 Cust_Expense。这个 Cust_Expense 表只有 250,000 个成员,并且希望通过加入客户编号从 SPECIFIC 月度 SAS 数据集中提取每个成员的费用数据。

Cust_Expense
------------
Customer_Number  Month
111              FEB2014
987              APR2017
784              FEB2014
768              APR2017
.....
145              AUG2017
345              AUG2014

我曾尝试使用调用执行,但它会尝试遍历输入数据集 (Cust_Expense) 的每 250,000 条记录并加入相应的月度 SAS 客户表,这会花费太多时间。 有没有办法按月读取输入表(Cust_Expense),以便我们读取特定月份的所有客户,然后读取同一个月表一次以提取该月的所有记录,这样它就不会循环 250,000 次。

【问题讨论】:

  • 您希望结果是什么样的?
  • @Joe,您是说(以问题的形式,而不是批评的形式)询问所需的样本输出,以便我可以尝试提供输出所需结果的解决方案,这是指示不了解审核流程应该如何运作?
  • @user2877959 不,这是对您之前/之后的其他 cmets 的回应。他们已经被版主删除了,看起来像。您的回复很好(您的编辑很有帮助)。

标签: sas


【解决方案1】:

根据您想要的结果,您可以通过每月过滤 cust_expenses 并加入相应的每月数据集来创建每个月的输出

%macro want;
proc sql noprint;
select distinct month
into :months separated by ' '
from cust_expenses
;
quit;

proc sql;
%do i=1 %to %sysfunc(countw(&months));
  %let month=%scan(&months,&i,%str( ));
    create table want_&month. as
    select *
    from cust_expense(where=(month="&month.")) t1
    inner join cust_&month. t2
      on t1.customer_number=t2.customer_number
    ;
%end;
quit;
%mend;
%want;

或者您可以通过将所有每月数据集“合并”为一个并动态添加月份列来使用一个连接来获得一个输出。

%macro want;
proc sql noprint;
select distinct month
into :months separated by ' '
from cust_expenses
;
quit;

proc sql;
  create table want as
  select *
  from cust_expense t1
  inner join (
              %do i=1 %to %sysfunc(countw(&months));
                %let month=%scan(&months,&i,%str( ));
                %if &i>1 %then union;
                select *, "&month." as month
                from cust_&month
              %end;
             ) t2
    on t1.customer_number=t2.customer_number
     and t1.month=t2.month
  ;
quit;
%mend;
%want;

在任何一种情况下,我都没有真正看到将这些月度数据集与 cust_expense 数据集连接起来的意义。后者似乎不包含每月数据集中尚不存在的任何信息。

【讨论】:

  • 我尝试了您的第一个解决方案,它似乎有效。我遇到了一个错误,即 where 子句运算符需要兼容的变量。
  • monthcust_expense 中的数值变量吗?
  • 我使用了 input(month,mon77y.) 并且成功了。第一个解决方案效果很好。谢谢!我尝试运行您的第二个解决方案,它运行良好,但输出不正确。不确定 %if &i>1 %then union;是问题所在。
【解决方案2】:

您的第一个,最好的答案是摆脱这些每月单独的表,并将它们变成一个以 ID 和月份为键的大表。然后你可以简单地加入这个并继续你的方式。拥有许多像这样的单独表格,其中数据元素确定它们所在的表格绝不是一个好主意。然后按月索引以使其更快。

如果您不能这样做,请尝试创建一个将所有这些表合并的视图。这样做可能会更快; SAS 可能决定具体化视图,但可能不会(但如果速度非常慢,请查看您的临时表空间,看看是否发生了这种情况)。

那么第三个选项可能是使用 SAS 格式。使用CNTLIN option 将较小的表格转换为格式。然后一个大数据步将允许您执行连接。

data want;
  set jan feb mar apr ... ;
  where put(id,CUSTEXPF1.) = '1';
run;

这只需要一次通过 250k 表,一次通过每月表,再加上非常非常快速的格式查找,这在这个数据步骤中无疑是零成本(因为磁盘 i/o 会更慢)。

【讨论】:

  • 这也是我的方法。合并所有数据集仍然不会很大,每月“只有”200 万条记录。您可能需要添加的一件事是数据相关的月份,正如 OP 所说的 2 列是客户编号和费用金额。显然这可以通过解析数据集名称来完成,使用indsname
【解决方案3】:

我猜你可以像这个例子一样在特定的数据集中输出你的数据:

data test;
infile datalines dsd;
   input ID : $2. MONTH  $3. ;
   datalines;
1,JAN
2,JAN
3,JAN
4,FEB
5,FEB
6,MAR
7,MAR
8,MAR
9,MAR
; 
run;

data  JAN FEB MAR;
set test;
if MONTH = "JAN" then output JAN;
if MONTH = "FEB" then output FEB;
if MONTH = "MAR" then output MAR;
run;

您将避免遍历所有 ID (250000) 您将使用来自 SAS 的数据集语句

最后你会得到 12 个包含相关 ID 的 DATASET。

如果是 FEB2014 ,例如,您将使用子字符串函数,数据集中的条件将变为:

...
set test;
...
if SUBSTR(MONTH,1,3)="FEB" then output FEB;
...

问候

【讨论】:

  • 我不认为你理解这个问题;这似乎根本无法回答他们在做什么。
  • 可能我不太理解这个问题。但是问题还不够清楚(没有代码源)。我相信我已经尽力了。问候
猜你喜欢
  • 2017-10-31
  • 1970-01-01
  • 2022-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多