【问题标题】:How can I assign values to dataset based on time and overlapping numerical ranges? - SAS如何根据时间和重叠的数值范围为数据集分配值? - SAS
【发布时间】:2015-07-22 22:16:09
【问题描述】:

我有一个信用卡交易数据集(我们称之为“Trans”),其中包含交易金额、邮政编码日期。我有另一个数据集(我们称之为“Key”),它列出了基于 dategeocode 的销售税率。 Key 数据集还包括与由 2 个变量表示的每个地理编码相关联的一系列邮政编码:Zip Start 和 Zip End。

由于地理编码与邮政编码不一致,一些邮政编码范围会重叠。如果发生这种情况,我想使用与 Trans 中显示的邮政编码相关的最低销售税率。

跨数据集:

TransAmount TransDate TransZip
$200 01/07/1998 90010
$12 02/09/2002 90022

关键数据集:

Geocode Rate StartDate EndDate ZipStart ZipEnd
1001 .0825 199701 200012 90001 90084
1001 .085 200101 200812 90001 90084
1002 .0825 199701 200012 90022 90024
1002 .08 200101 200812 90022 90024

期望的输出:

TransAmount TransDate TransZip Rate
$200 01/07/1998 90010 .0825
$12 02/09/2002 90022 .08

我在 SAS 中使用了这个基本的 SQL 代码,但遇到了邮政编码重叠的问题。

 proc sql;
 create table output as
 select a.*, b.zipstart, b.zipend, b.startdate, b.enddate, b.rate
 from Trans.CA_Zip_Cd_Testing a left join Key.CA_rates b
  on a.TranZip ge b.zipstart
  and a.TranZip le b.zipend
  and a.TransDate ge b.StartDate
  and a.transDate le b.EndDate
;
quit;

【问题讨论】:

  • a) 为什么excel 在标签列表中? b) 尝试先创建一个邮政编码级别表,该表首先具有最低的费率,然后在上面的 sql 中使用它?
  • 谢谢乔。 a) 关键数据集在 Excel 中,所以也许解决方案可以在 Excel 中完成,正如你在 b) 中提到的那样,这是我的第一个想法,但是有 2500 多个唯一的邮政编码和重叠,它仍然很棘手。另外,我在 SAS 中处理矩阵的经验并不多。

标签: sas overlap transpose


【解决方案1】:

就查询部分而言,最简单的方法是添加一个子查询来获取最低速率。

Select t.transamount, t.transdate,t.transzip
        ,(Select MIN(rate) from Key where t.transzip between ZipStart and ZipEnd and t.transdate between startdate and enddate) 'Rate'
from trans t

您也可以将其作为子查询并加入它。

【讨论】:

  • 在样本上进行了测试,它似乎工作得很好。谢谢! A+ 保持简洁。
  • 答案运行良好,但与我的其他查询相比,运行时间过长(10% 的数据样本需要 40 分钟)。您能否详细说明使用子查询和连接逻辑的另一个选项?我不知道如何加入它,因为它本质上是一个条件查找。
【解决方案2】:

SAS SQL 优化器有时会很不错。其他时候,这可能是一个挑战。这段代码会稍微复杂一些,但它可能会更快,并且会受到键表的大小限制。

data key;
set key;
   dummy_key=1;
run;

data want(drop=dummy_key geocode rate startDate endDate zipStart zipEnd rc i);
if _n_ = 1 then do;
 if 0 then set key;
 declare hash k (dataset:'key',multidata:'y');
 k.defineKey('dummy_key');
 k.defineData('geocode','rate','startdate','enddate','zipstart','zipend');
 k.defineDone();
end;
call missing (of _all_);
set trans;
dummy_key=1;

rc = k.find();
do i=1 to 1000 while (rc=0);
transZipNum = input(transZip,8.); *converts character zip to number. if its    already a number then remove;
zipStartNum = input(zipStart,8.);
zipEndNum = input(zipEnd,8.);

if startDate <= transDate <= endDate then do;
     if zipStartNum <= transZipNum <= zipEndNum then do;
          rate_out = min(rate_out,rate);
     end;
end;
rc=k.find_next();
end;
run;

【讨论】:

  • 感谢您的回复。我收到“变量 dummy_key 不在文件 WORK.KEY 上”的错误。我尝试在 'set key;' 之后设置 dummy_key=1声明,但这仍然不起作用。我错过了什么吗?
  • 它必须在准备步骤中添加。我编辑了代码以反映将要发生的事情。
  • 谢谢。如果实际的 Key 文件是 12000 条记录,是否必须增加 do 循环才能覆盖?
  • 是的。 i=1 到 1000 代码是防止无限循环的“最佳实践”。因此,它需要足够大以遍历所有可能的行。我会将其更改为高于您认为可能在键表中的最高行的数字。
猜你喜欢
  • 2014-01-01
  • 1970-01-01
  • 2022-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 2018-07-05
  • 2022-11-18
相关资源
最近更新 更多