SAS 合并不工作
SAS Merge By Not Working
以下是我编写的一个宏,用于遗漏连接两个数据集。
/*
* Macro to add the t-rate to the data
*/
%MACRO RFRATE(WITHOUT_RATE, WITH_RATE);
/*read the tbill rate data*/
data TBRATE;
INFILE "T-RATE/T-RATE-FORMATTED.csv"
DELIMITER = ","
MISSOVER DSD
FIRSTOBS=2
LRECL=32767;
INPUT DATE one_M three_M six_M one_Y two_Y three_Y five_Y seven_Y ten_Y twenty_Y thirty_Y;
format DATE yymmddn8.;
length Date 4;
run;
data &WITH_RATE;
merge &WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A;
run;
/*I have also tried the following way (SQL)*/
/*
PROC SQL;
Create table &WITH_RATE as
Select a.*,b.*
from
&WITHOUT_RATE a
left join
TBRATE b
on a.Date=b.Date;
quit;
*/
proc export data=&WITH_RATE (obs=99999)
outfile= 'samplesmall.csv'
dbms=CSV REPLACE;
putname=YES;
run;
proc contents data= TBRATE position;
run;
proc contents data= &WITHOUT_RATE position;
run;
%mend;
TBRATE是一些类似于以下格式的数据:
| Date | Rate |
|----------|----------|
| 20120101 | 1.0 |
| 20120102 | 1.5 |
| 20120103 | 1.5 |
| 20120104 | 1.3 |
| 20120105 | 1.1 |
WITHOUT_RATE是一些类似于下面的数据:
| Date | Other Data |
|----------|---------------|
| 20120101 | 7.0 |
| 20120101 | 3.5 |
| 20120101 | 4.5 |
| 20120101 | 2.3 |
| 20120101 | 11.1 |
| 20120102 | 23.0 |
| 20120102 | 12.5 |
| 20120102 | 12.5 |
| 20120102 | 11.3 |
| 20120102 | 11.1 |
我想创建类似于以下内容的内容:
| Date | Other Data | Rate |
|----------|---------------|----------
| 20120101 | 7.0 | 1.0 |
| 20120101 | 3.5 | 1.0 |
| 20120101 | 4.5 | 1.0 |
| 20120101 | 2.3 | 1.0 |
| 20120101 | 11.1 | 1.0 |
| 20120102 | 23.0 | 1.5 |
| 20120102 | 12.5 | 1.5 |
| 20120102 | 12.5 | 1.5 |
| 20120102 | 11.3 | 1.5 |
| 20120102 | 11.1 | 1.5 |
WITHOUT_RATE中日期变量的格式为:
Variable Type Len Format Label
DATE Num 4 YYMMDDN8. Quote date
TBRATE 中日期变量的格式为:
Variable Type Len Format
DATE Num 4 YYMMDDN8.
看来他们是一样的。
但是,代码不断产生空结果:
| Date | Other Data | Rate |
|----------|---------------|----------
| 20120101 | 7.0 | |
| 20120101 | 3.5 | |
| 20120101 | 4.5 | |
| 20120101 | 2.3 | |
| 20120101 | 11.1 | |
| 20120102 | 23.0 | |
| 20120102 | 12.5 | |
| 20120102 | 12.5 | |
| 20120102 | 11.3 | |
| 20120102 | 11.1 | |
所以,我想知道我哪里错了?
更新#2
The code used to call the macro:
/*The output dataset*/
%NBBO(20130102, tempoutputset);
%NBBOReturn(tempoutputset, NBBODATA);
%RFRATE(NBBODATA, RFRATEDATA);
从 data merge
语句中删除 set
。您不能在 Data Merge 语句中写入 set。您还需要对数据集进行排序,如果它们尚未按日期默认排序,以便在日期合并:-
Proc sort data=&WITHOUT_RATE; by Date; run;
Proc sort data=TBRATE; by Date; run;
data &WITH_RATE;
merge &WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A;
run;
OR
PROC SQL:
Create table &WITH_RATE as
Select a.*,b.Rate
from
&WITHOUT_RATE a
left join
TBRATE b
on a.Date=b.Date;
quit;
同意@Reeza 的观点,我将删除宏代码以查找问题的根源。一旦你让它在宏语言之外工作,就回去处理宏。快速浏览一下,我猜你的 BY 值不匹配。
尝试类似下面的操作来查看不匹配的记录:
data WITH_RATE
Aonly
Bonly
BothAandB
;
merge WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A then output With_Rate;
if A=1 and B=1 then output BothAandB;
else if B=0 then output Aonly;
else if A=0 then output Bonly;
run;
然后删除日期的格式并查看 Aonly 和 Bonly 中的值以了解它们不匹配的原因。输出数据集 Aonly 将包含来自 WITHOUT_RATE 的记录,这些记录在 TBRATE 中没有匹配的日期。输出数据集 Bonly 将包含来自 TBRATE 的记录,这些记录在 WITHOUT_RATE 中没有匹配的日期。输出数据集 BothAandB 将包含匹配的记录。
如果您看到 Aonly 和 Bonly 中的值看起来应该匹配,并且假设这些是日期,也许在合并之前将它们四舍五入以确保它们是整数以避免任何可能的数字精度/浮点差异。
我解决了。感谢@Quentin 和@India.Rocket 的建议,我找到了解决方案。
问题是从 csv 文件中读取日期。 yyyymmdd 或 yyyy-mm-dd 格式的日期似乎无法正确读取。我不得不用 python 将 csv 中的日期重新格式化为 mm/dd/yyyy,然后在 sas 中将它们输入为 DATE:mmddyy10。但是,我要合并的另一个数据集的日期格式为 yymmddn8。因此,我不得不重新格式化 DATE:mmddyy10。到 yymmddn8。使整个事情正常进行。
使用了以下代码。
data TBRATE;
INFILE "T-RATE/T-RATE-FORMATTED.csv"
DELIMITER = ","
MISSOVER DSD
FIRSTOBS=2
LRECL=32767;
INPUT DATE:mmddyy10. DateRaw one_M three_M six_M one_Y two_Y three_Y five_Y seven_Y ten_Y twenty_Y thirty_Y;
format DATE yymmddn8.;
run;
以下是我编写的一个宏,用于遗漏连接两个数据集。
/*
* Macro to add the t-rate to the data
*/
%MACRO RFRATE(WITHOUT_RATE, WITH_RATE);
/*read the tbill rate data*/
data TBRATE;
INFILE "T-RATE/T-RATE-FORMATTED.csv"
DELIMITER = ","
MISSOVER DSD
FIRSTOBS=2
LRECL=32767;
INPUT DATE one_M three_M six_M one_Y two_Y three_Y five_Y seven_Y ten_Y twenty_Y thirty_Y;
format DATE yymmddn8.;
length Date 4;
run;
data &WITH_RATE;
merge &WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A;
run;
/*I have also tried the following way (SQL)*/
/*
PROC SQL;
Create table &WITH_RATE as
Select a.*,b.*
from
&WITHOUT_RATE a
left join
TBRATE b
on a.Date=b.Date;
quit;
*/
proc export data=&WITH_RATE (obs=99999)
outfile= 'samplesmall.csv'
dbms=CSV REPLACE;
putname=YES;
run;
proc contents data= TBRATE position;
run;
proc contents data= &WITHOUT_RATE position;
run;
%mend;
TBRATE是一些类似于以下格式的数据:
| Date | Rate |
|----------|----------|
| 20120101 | 1.0 |
| 20120102 | 1.5 |
| 20120103 | 1.5 |
| 20120104 | 1.3 |
| 20120105 | 1.1 |
WITHOUT_RATE是一些类似于下面的数据:
| Date | Other Data |
|----------|---------------|
| 20120101 | 7.0 |
| 20120101 | 3.5 |
| 20120101 | 4.5 |
| 20120101 | 2.3 |
| 20120101 | 11.1 |
| 20120102 | 23.0 |
| 20120102 | 12.5 |
| 20120102 | 12.5 |
| 20120102 | 11.3 |
| 20120102 | 11.1 |
我想创建类似于以下内容的内容:
| Date | Other Data | Rate |
|----------|---------------|----------
| 20120101 | 7.0 | 1.0 |
| 20120101 | 3.5 | 1.0 |
| 20120101 | 4.5 | 1.0 |
| 20120101 | 2.3 | 1.0 |
| 20120101 | 11.1 | 1.0 |
| 20120102 | 23.0 | 1.5 |
| 20120102 | 12.5 | 1.5 |
| 20120102 | 12.5 | 1.5 |
| 20120102 | 11.3 | 1.5 |
| 20120102 | 11.1 | 1.5 |
WITHOUT_RATE中日期变量的格式为:
Variable Type Len Format Label
DATE Num 4 YYMMDDN8. Quote date
TBRATE 中日期变量的格式为:
Variable Type Len Format
DATE Num 4 YYMMDDN8.
看来他们是一样的。
但是,代码不断产生空结果:
| Date | Other Data | Rate |
|----------|---------------|----------
| 20120101 | 7.0 | |
| 20120101 | 3.5 | |
| 20120101 | 4.5 | |
| 20120101 | 2.3 | |
| 20120101 | 11.1 | |
| 20120102 | 23.0 | |
| 20120102 | 12.5 | |
| 20120102 | 12.5 | |
| 20120102 | 11.3 | |
| 20120102 | 11.1 | |
所以,我想知道我哪里错了?
更新#2
The code used to call the macro:
/*The output dataset*/
%NBBO(20130102, tempoutputset);
%NBBOReturn(tempoutputset, NBBODATA);
%RFRATE(NBBODATA, RFRATEDATA);
从 data merge
语句中删除 set
。您不能在 Data Merge 语句中写入 set。您还需要对数据集进行排序,如果它们尚未按日期默认排序,以便在日期合并:-
Proc sort data=&WITHOUT_RATE; by Date; run;
Proc sort data=TBRATE; by Date; run;
data &WITH_RATE;
merge &WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A;
run;
OR
PROC SQL:
Create table &WITH_RATE as
Select a.*,b.Rate
from
&WITHOUT_RATE a
left join
TBRATE b
on a.Date=b.Date;
quit;
同意@Reeza 的观点,我将删除宏代码以查找问题的根源。一旦你让它在宏语言之外工作,就回去处理宏。快速浏览一下,我猜你的 BY 值不匹配。
尝试类似下面的操作来查看不匹配的记录:
data WITH_RATE
Aonly
Bonly
BothAandB
;
merge WITHOUT_RATE(IN=A) TBRATE(IN=B);
by Date;
if A then output With_Rate;
if A=1 and B=1 then output BothAandB;
else if B=0 then output Aonly;
else if A=0 then output Bonly;
run;
然后删除日期的格式并查看 Aonly 和 Bonly 中的值以了解它们不匹配的原因。输出数据集 Aonly 将包含来自 WITHOUT_RATE 的记录,这些记录在 TBRATE 中没有匹配的日期。输出数据集 Bonly 将包含来自 TBRATE 的记录,这些记录在 WITHOUT_RATE 中没有匹配的日期。输出数据集 BothAandB 将包含匹配的记录。
如果您看到 Aonly 和 Bonly 中的值看起来应该匹配,并且假设这些是日期,也许在合并之前将它们四舍五入以确保它们是整数以避免任何可能的数字精度/浮点差异。
我解决了。感谢@Quentin 和@India.Rocket 的建议,我找到了解决方案。
问题是从 csv 文件中读取日期。 yyyymmdd 或 yyyy-mm-dd 格式的日期似乎无法正确读取。我不得不用 python 将 csv 中的日期重新格式化为 mm/dd/yyyy,然后在 sas 中将它们输入为 DATE:mmddyy10。但是,我要合并的另一个数据集的日期格式为 yymmddn8。因此,我不得不重新格式化 DATE:mmddyy10。到 yymmddn8。使整个事情正常进行。
使用了以下代码。
data TBRATE;
INFILE "T-RATE/T-RATE-FORMATTED.csv"
DELIMITER = ","
MISSOVER DSD
FIRSTOBS=2
LRECL=32767;
INPUT DATE:mmddyy10. DateRaw one_M three_M six_M one_Y two_Y three_Y five_Y seven_Y ten_Y twenty_Y thirty_Y;
format DATE yymmddn8.;
run;