【发布时间】:2021-05-29 12:59:38
【问题描述】:
长话短说,我需要比较两个数据集(A 和 B)。 B 应该是 A 的副本,但在 Impala 服务器上。每天我都通过 SQL 传递从 Impala 服务器将B 检索到 SAS。
我正在编写一个每天都会运行的程序,以确保这两个数据集 1:1 匹配。 但是,我在数值近似(精度)上苦苦挣扎。
这里是 A 的一个例子:
| ID | value |
|---|---|
| 01 | 0 |
| 02 | 5000 |
| 03 | 978908.69 |
| 04 | 109789503.12 |
| 05 | 49505954.92 |
为了进行比较,我将conc 列中的两列连接起来,然后比较A 和B。
data want;
set have;
conc=cats(id,value);
run;
这基本上适用于除一个之外的所有观察。
观察值具有A 的9128554507.9 和B 的9128554507.8 的值。没有格式或信息应用于变量。
但是,当在 value 变量上应用 comma32.30 格式时,我看到 A 和 B 的值是相同的 9128554507.850000000000000000000。所以他们应该是一样的。
然后我在CATS函数的文档中看到了以下内容
CATS 函数从数字中删除前导和尾随空格 使用 BESTw 格式化数值后的参数。格式。
然后我认为将数字变量转换为字符变量是一个好主意。 我是用这个宏做的:
/*macro to convert all numeric to char*/
%macro vars(dsn, outp);
%let list=;
%let type=;
%let dsid=%sysfunc(open(&dsn));
%let cnt=%sysfunc(attrn(&dsid,nvars));
%do i = 1 %to &cnt;
%let list=&list %sysfunc(varname(&dsid,&i));
%let type=&type %sysfunc(vartype(&dsid,&i));
%end;
%let rc=%sysfunc(close(&dsid));
data &outp(drop=
%do i = 1 %to &cnt;
%let temp=%scan(&list,&i);
_&temp
%end;);
set &dsn(rename=(
%do i = 1 %to &cnt;
%let temp=%scan(&list,&i);
&temp=_&temp
%end;));
%do j = 1 %to &cnt;
%let temp=%scan(&list,&j);
/** Change C to N for numeric to character conversion **/
%if %scan(&type,&j) = N %then %do;
/** Also change INPUT to PUT for numeric to character **/
&temp=PUT(_&temp,best.);
%end;
%else %do;
&temp=_&temp;
%end;
%end;
run;
%mend vars;
看到使用了best. 格式。不幸的是,我最终得到了与以前相同的值,9128554507.9 的A 和9128554507.8 的B 的值。我不知道这两个数据集之间发生了什么? “真实”值似乎是相同的,但是当对两者应用 best. 格式时,SAS 将 A 的值四舍五入为 .9,将 B 的值四舍五入为 .8。
有什么解决方法吗?尝试在数据线语句中手动输入观察结果时,我无法重现该错误。我不想将值四舍五入为预定义的小数。理想情况下,我希望将两个表的值动态截断为number of actual decimal - 1(例如3462829.374 变为3462829.37 和18726347.39 变为18726347.3),然后比较它们。
【问题讨论】:
-
我认为目标是比较它们,那么为什么要连接两个变量呢?为什么不直接使用原始的两个变量进行比较?
-
在更大的问题中,我在 A 和 B 中有大约 15 列。我将它们连接起来并使用 md5() 来计算我在两个表之间进行比较的哈希值。我只显示了变量(值),因为这是唯一导致问题的变量。
-
我很好奇你为什么在数据步骤中使用宏函数而不是数组。这将使代码更易于使用。
标签: sas comparison