SAS:数据合并简介

数据合并,即两个或者多个数据集的数据合并到一个数据集中,常见的方式有3种,分别是 one-to-one reading、concatenating 和 Match-merging,其中只有最后一种Match-merging是要求匹配字段是已经排好序的。

 

在介绍之前,准备两个基础数据,是已经按照ID排好序的

cert.patdat

Obs ID Age Sex Date
1 A001 21 M 08/17/1997
2 A002 32 M 02/18/1986
3 A003 24 F 06/07/1994
4 A004 28 M 01/27/1990
5 A005 44 F 04/24/1974
6 A007 39 M 07/10/1979
7 A008 30 F 09/16/1988

 

cert.visit

Obs ID Visit SysBP DiasBP Weight Date
1 A001 1 140 85 195 11/05/2009
2 A001 2 138 90 198 10/13/2009
3 A001 3 145 95 200 07/04/2009
4 A002 1 121 75 168 04/14/2009
5 A003 1 118 68 125 08/12/2009
6 A003 2 112 65 123 08/21/2009
7 A004 1 143 86 204 03/30/2009
8 A005 1 132 76 174 02/27/2009
9 A005 2 132 78 175 07/11/2009
10 A005 3 134 78 176 04/16/2009
11 A008 1 126 80 182 05/22/2009

 

下面分别看一下三种方式

one-to-one reading

工作原理

SAS:数据合并简介_第1张图片 one-to-one reading

 

创建一个新的数据集,新的数据集包含所有的变量。

根据每个观测在数据集中的位置去匹配,第2个数据集中变量的值会覆盖第1个数据集中变量的值。

结果集中观测的数量和数据量较少的那个数据集一样。

说简单一点,就是先从第1个数据集拿一行,然后再从第2个数据集拿一行去覆盖第1个数据集中数据。以次类推,直到有一个数据集结束。

 

语法

DATA output-SAS-data-set;

 SET SAS-data-set-1;

 SET SAS-data-set-2;

RUN;

 

示例

libname cert 'J:\sas_guide_data\base-guide-practice-data\cert';

data tmp1;
 set cert.patdat;
 set cert.visit;
run;

proc print data=tmp1;
run;

输出:

Obs ID Age Sex Date Visit SysBP DiasBP Weight
1 A001 21 M 11/05/2009 1 140 85 195
2 A001 32 M 10/13/2009 2 138 90 198
3 A001 24 F 07/04/2009 3 145 95 200
4 A002 28 M 04/14/2009 1 121 75 168
5 A003 44 F 08/12/2009 1 118 68 125
6 A003 39 M 08/21/2009 2 112 65 123
7 A004 30 F 03/30/2009 1 143 86 204

可以看到,两个数据集都有的变量ID和Date,结果集中只出现1次,且被第2个数据集的值覆盖。

当然,上面这个例子没有实际的意义,下图中的例子才有实际的意义:

SAS:数据合并简介_第2张图片

 

concatenating

 

工作原理

SAS:数据合并简介_第3张图片 concatenating

即将两个数据集连接起来

 

语法

DATA output-SAS-data-set;

 SET SAS-data-set-1

         SAS-data-set-2;

RUN;

 

示例

data tmp2;
 set cert.patdat
     cert.visit;
run;

proc print data=tmp2;
run;

输出:

Obs ID Age Sex Date Visit SysBP DiasBP Weight
1 A001 21 M 08/17/1997 . . . .
2 A002 32 M 02/18/1986 . . . .
3 A003 24 F 06/07/1994 . . . .
4 A004 28 M 01/27/1990 . . . .
5 A005 44 F 04/24/1974 . . . .
6 A007 39 M 07/10/1979 . . . .
7 A008 30 F 09/16/1988 . . . .
8 A001 .   11/05/2009 1 140 85 195
9 A001 .   10/13/2009 2 138 90 198
10 A001 .   07/04/2009 3 145 95 200
11 A002 .   04/14/2009 1 121 75 168
12 A003 .   08/12/2009 1 118 68 125
13 A003 .   08/21/2009 2 112 65 123
14 A004 .   03/30/2009 1 143 86 204
15 A005 .   02/27/2009 1 132 76 174
16 A005 .   07/11/2009 2 132 78 175
17 A005 .   04/16/2009 3 134 78 176
18 A008 .   05/22/2009 1 126 80 182

同样的,两个数据集都有的变量ID和Date,只出现一次, 但因为这个是连接,所以不存在值覆盖问题。

同样的,上面的例子没有实际意义,只是为了展示工作原理,下面的例子才有实际意义:

SAS:数据合并简介_第4张图片

 

Match-merging

工作原理

SAS:数据合并简介_第5张图片 Match-merging

这个就是merge了,按照某个字段的值进行匹配,如果匹配上,就合并到一条记录中。

 

语法

DATA output-SAS-data-set;

 MERGE SAS-data-set-1

               SAS-data-set-2;

 BY <DESCENDING> variable(s);

RUN;

 

示例

data tmp2;
 merge cert.patdat
       cert.visit;
 by id;
run;

proc print data=tmp2;
run;

输出

Obs ID Age Sex Date Visit SysBP DiasBP Weight
1 A001 21 M 11/05/2009 1 140 85 195
2 A001 21 M 10/13/2009 2 138 90 198
3 A001 21 M 07/04/2009 3 145 95 200
4 A002 32 M 04/14/2009 1 121 75 168
5 A003 24 F 08/12/2009 1 118 68 125
6 A003 24 F 08/21/2009 2 112 65 123
7 A004 28 M 03/30/2009 1 143 86 204
8 A005 44 F 02/27/2009 1 132 76 174
9 A005 44 F 07/11/2009 2 132 78 175
10 A005 44 F 04/16/2009 3 134 78 176
11 A007 39 M 07/10/1979 . . . .
12 A008 30 F 05/22/2009 1 126 80 182

可以看到,两个数据集都有的变量Date,输出中只出现一次, 且被第2个数据集的值覆盖(ID是匹配字段,所以谈不上覆盖),这是第一个问题。

另外一个问题是,结果集中的ID是包含了两个数据集中所有的值,无论是否能匹配上,比如A007只在数据集中patdat中出现过,如果想要结果集中只出现匹配的项怎么办?

针对这两个问题,都是有解决方案的。

问题1:patdat和visit中都有Date变量,但两者的含义并不相同,前者是出生日期,后者是指访问日期,如何避免被覆盖?答案是可以使用rename选项,选项语法为(RENAME=(old-variable-name=new-variable-name))

示例:

data tmp2;
 merge cert.patdat(RENAME=(Date=BirthDate))
       cert.visit(RENAME=(Date=VisitDate));
 by id;
run;

proc print data=tmp2;
run;

输出:

Obs ID Age Sex BirthDate Visit SysBP DiasBP Weight VisitDate
1 A001 21 M 08/17/1997 1 140 85 195 11/05/2009
2 A001 21 M 08/17/1997 2 138 90 198 10/13/2009
3 A001 21 M 08/17/1997 3 145 95 200 07/04/2009
4 A002 32 M 02/18/1986 1 121 75 168 04/14/2009
5 A003 24 F 06/07/1994 1 118 68 125 08/12/2009
6 A003 24 F 06/07/1994 2 112 65 123 08/21/2009
7 A004 28 M 01/27/1990 1 143 86 204 03/30/2009
8 A005 44 F 04/24/1974 1 132 76 174 02/27/2009
9 A005 44 F 04/24/1974 2 132 78 175 07/11/2009
10 A005 44 F 04/24/1974 3 134 78 176 04/16/2009
11 A007 39 M 07/10/1979 . . . . .
12 A008 30 F 09/16/1988 1 126 80 182 05/22/2009

可以看到输出中的BirthDate和VisitDate各占了一个变量

 

问题2:merge的时候如何只显示真正匹配上的行?

答案是可以使用IN选项,选项语法为IN=variable,它创建一个临时变量,如果当前观测对结果集有用,那么该变量值会被设置为1,否则设置为0,在匹配的时候加上IF关健字判断即可。注:这个变量并不会出现在结果集中。

示例:

data tmp2;
 merge cert.patdat(IN=tmpvar1 RENAME=(Date=BirthDate))
       cert.visit(IN=tmpvar2 RENAME=(Date=VisitDate));
 by id;
 if tmpvar1 eq 1 AND tmpvar2 eq 1;
run;

proc print data=tmp2;
run;

输出:

Obs ID Age Sex BirthDate Visit SysBP DiasBP Weight VisitDate
1 A001 21 M 08/17/1997 1 140 85 195 11/05/2009
2 A001 21 M 08/17/1997 2 138 90 198 10/13/2009
3 A001 21 M 08/17/1997 3 145 95 200 07/04/2009
4 A002 32 M 02/18/1986 1 121 75 168 04/14/2009
5 A003 24 F 06/07/1994 1 118 68 125 08/12/2009
6 A003 24 F 06/07/1994 2 112 65 123 08/21/2009
7 A004 28 M 01/27/1990 1 143 86 204 03/30/2009
8 A005 44 F 04/24/1974 1 132 76 174 02/27/2009
9 A005 44 F 04/24/1974 2 132 78 175 07/11/2009
10 A005 44 F 04/24/1974 3 134 78 176 04/16/2009
11 A008 30 F 09/16/1988 1 126 80 182 05/22/2009

可以看到,结果集只有11个了。A007没有匹配上

 

参考资料:

SAS Certified Specialist Prep Guide

 

 

你可能感兴趣的:(办公)