SAS:数据合并简介

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

 

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

cert.patdat

ObsIDAgeSexDate
1A00121M08/17/1997
2A00232M02/18/1986
3A00324F06/07/1994
4A00428M01/27/1990
5A00544F04/24/1974
6A00739M07/10/1979
7A00830F09/16/1988

 

cert.visit

ObsIDVisitSysBPDiasBPWeightDate
1A00111408519511/05/2009
2A00121389019810/13/2009
3A00131459520007/04/2009
4A00211217516804/14/2009
5A00311186812508/12/2009
6A00321126512308/21/2009
7A00411438620403/30/2009
8A00511327617402/27/2009
9A00521327817507/11/2009
10A00531347817604/16/2009
11A00811268018205/22/2009

 

下面分别看一下三种方式

one-to-one reading

工作原理

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;

输出:

ObsIDAgeSexDateVisitSysBPDiasBPWeight
1A00121M11/05/2009114085195
2A00132M10/13/2009213890198
3A00124F07/04/2009314595200
4A00228M04/14/2009112175168
5A00344F08/12/2009111868125
6A00339M08/21/2009211265123
7A00430F03/30/2009114386204

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

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

 

concatenating

 

工作原理

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;

输出:

ObsIDAgeSexDateVisitSysBPDiasBPWeight
1A00121M08/17/1997....
2A00232M02/18/1986....
3A00324F06/07/1994....
4A00428M01/27/1990....
5A00544F04/24/1974....
6A00739M07/10/1979....
7A00830F09/16/1988....
8A001. 11/05/2009114085195
9A001. 10/13/2009213890198
10A001. 07/04/2009314595200
11A002. 04/14/2009112175168
12A003. 08/12/2009111868125
13A003. 08/21/2009211265123
14A004. 03/30/2009114386204
15A005. 02/27/2009113276174
16A005. 07/11/2009213278175
17A005. 04/16/2009313478176
18A008. 05/22/2009112680182

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

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

 

Match-merging

工作原理

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;

输出

ObsIDAgeSexDateVisitSysBPDiasBPWeight
1A00121M11/05/2009114085195
2A00121M10/13/2009213890198
3A00121M07/04/2009314595200
4A00232M04/14/2009112175168
5A00324F08/12/2009111868125
6A00324F08/21/2009211265123
7A00428M03/30/2009114386204
8A00544F02/27/2009113276174
9A00544F07/11/2009213278175
10A00544F04/16/2009313478176
11A00739M07/10/1979....
12A00830F05/22/2009112680182

可以看到,两个数据集都有的变量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;

输出:

ObsIDAgeSexBirthDateVisitSysBPDiasBPWeightVisitDate
1A00121M08/17/199711408519511/05/2009
2A00121M08/17/199721389019810/13/2009
3A00121M08/17/199731459520007/04/2009
4A00232M02/18/198611217516804/14/2009
5A00324F06/07/199411186812508/12/2009
6A00324F06/07/199421126512308/21/2009
7A00428M01/27/199011438620403/30/2009
8A00544F04/24/197411327617402/27/2009
9A00544F04/24/197421327817507/11/2009
10A00544F04/24/197431347817604/16/2009
11A00739M07/10/1979.....
12A00830F09/16/198811268018205/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;

输出:

ObsIDAgeSexBirthDateVisitSysBPDiasBPWeightVisitDate
1A00121M08/17/199711408519511/05/2009
2A00121M08/17/199721389019810/13/2009
3A00121M08/17/199731459520007/04/2009
4A00232M02/18/198611217516804/14/2009
5A00324F06/07/199411186812508/12/2009
6A00324F06/07/199421126512308/21/2009
7A00428M01/27/199011438620403/30/2009
8A00544F04/24/197411327617402/27/2009
9A00544F04/24/197421327817507/11/2009
10A00544F04/24/197431347817604/16/2009
11A00830F09/16/198811268018205/22/2009

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

 

参考资料:

SAS Certified Specialist Prep Guide

 

 

  • 9
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值