r - 如何在 R studio 中使用 do loop 制作相当于 SAS 宏的内容?
问题描述
我有一堆名为“haveyear”的 SAS 数据集,范围从 2000 年到 2018 年,即"have2000"-"have2018"
. 这些存储在本地目录中'path_to_have_data'
。每个数据集包含几个变量,即var1
,var2
等等。我想加载这些数据集,然后var1 ne '0'
根据原始数据集对它们进行子集化,并保留 var1 和 var2。此外,我想为year
每个子集添加一个新变量,这样我就可以知道数据来自哪一年。最后,我想将所有新子集附加(堆叠)到一个名为appended
. 例如:
数据集Have2017
如下所示:
var1 var2 var3
0 2 5
3 7 9
数据集Have2018
如下所示:
var1 var2 var3
0 2 5
3 7 9
子集Want2017
如下所示:
var1 var2 year
3 7 2017
子集Want2018
如下所示:
var1 var2 year
3 7 2018
最终的数据集appended
如下所示:
var1 var2 year
3 7 2017
3 7 2018
以下 SAS 脚本可以解决问题:
libname raw 'path_to_have_data';
%macro a;
%do &year.=2000 %to 2018;
data want&year. (keep= var1 var2);
set raw.have&year.;
where var1 ne '0';
year=&year.;
run;
%end;
%mend;
%a;
data appended;
set want:;
run;
有谁知道如何使用 R Studio 实现相同的结果?
编辑:问题的MCVE版本
这是从原始帖子产生所需结果所需的 SAS 代码的工作版本。
首先,需要一个 DATA 步来创建一些 SAS 数据集。我们将它们存储在默认WORK
库中,而不是引用磁盘上的另一个库。
/* generate sample data */
data have2000 have2001 have2002;
input var1 var2 var3;
cards;
0 1 2
1 3 5
2 7 4
0 9 9
8 7 3
;
run;
接下来,我们需要对 SAS 宏进行一些编辑以使其运行。
/* run macro from OP */
options mprint; /* shows SAS code generated by macro processor */
/*
* corrections / adjustments made to macro
* 1. remove & in %do loop
* 2. add year to keep list
* 3. fix syntax error in where statement because var1 is numeric
* 4. use work library, and only process 3 years of data
*/
%macro a;
%do year = 2000 %to 2002;
data want&year. (keep= var1 var2 year);
set have&year.;
where var1 ne 0;
year=&year.;
run;
%end;
%mend;
/* run the macro */
%a;
SAS 选项mprint
使 SAS 将宏生成的代码写入日志。当我们运行宏时,为单个数据集生成的代码子集如下所示。
MPRINT(A): data want2000 (keep= var1 var2 year);
MPRINT(A): set have2000;
MPRINT(A): where var1 ne 0;
MPRINT(A): year=2000;
MPRINT(A): run;
MPRINT(A): data want2001 (keep= var1 var2 year);
MPRINT(A): set have2001;
MPRINT(A): where var1 ne 0;
MPRINT(A): year=2001;
MPRINT(A): run;
MPRINT(A): data want2002 (keep= var1 var2 year);
MPRINT(A): set have2002;
MPRINT(A): where var1 ne 0;
MPRINT(A): year=2002;
MPRINT(A): run;
该宏生成三个 SAS 数据步骤,每年一个,包括以下更改。
- 降低
var3
- 删除行
var1 = 0
- 将输出写入名为的 SAS 数据集
want<year>
最后,代码将刚刚创建的数据集组合成一个名为appended
. 我们还将打印结果数据集。
data appended;
set want:; /* references all SAS datasets that start with "want" */
run;
proc print data = appended;
run;
...和输出:
解决方案
这是该问题的Base R解决方案。OP 希望复制 SAS 宏的过程,该过程将 SAS 数据集列表 raw.have2000 - raw.have2018 子集化,保留两列,设置一个year
等于数据集名称中列出的年份的变量,并将这些加入单个数据集。
# create some data
var1 <- 0:5
var2 <- 6:11
var3 <- 12:17
raw.have2000 <- data.frame(var1,var2,var3)
raw.have2001 <- data.frame(var1,var2,var3)
raw.have2002 <- data.frame(var1,var2,var3)
years <- 2000:2002
dataList <- lapply(years,function(x){
# create name of data set as a character object
dsname <- paste0("raw.have",x)
# use dsname with get() to extract data and subset first 2 variables
ds <- subset(get(dsname),var1 !=0,select=c(var1,var2))
ds$year <- x
# print to have data frame returned in
# output list
ds
})
# combine data frames
appended <- do.call(rbind,dataList)
...并且输出,注意到var1 = 0
已被消除的行var3
已被删除,并且year
已添加变量:
> appended
var1 var2 year
2 1 7 2000
3 2 8 2000
4 3 9 2000
5 4 10 2000
6 5 11 2000
21 1 7 2001
31 2 8 2001
41 3 9 2001
51 4 10 2001
61 5 11 2001
22 1 7 2002
32 2 8 2002
42 3 9 2002
52 4 10 2002
62 5 11 2002
>
解释
SAS 和 R 之间的主要区别之一是经验丰富的 SAS 程序员使用 SAS 宏语言来自动执行重复性任务。宏语言生成由 SAS 系统处理的 SAS 代码。
R 没有宏语言/代码生成器。但是,可以使用该get()
函数访问 R 对象,这些对象的名称可以通过将各种信息组合成字符对象来生成。
推荐阅读
- vue.js - Window.resize 或 document.resize 哪个有效,哪个无效?VueJS
- javascript - 从鼠标选择后未选择 jQuery UI 自动完成值
- wcf - wcf 托管在 Windows 服务和 httpbindings 中
- vba - Outlook 中用于密码保护附件文件的 VBA 插件
- javascript - 有没有办法使用 AJAX 将响应结果传递到另一个页面
- angular - Angular 和 FabricJS 类变量和事件
- c - 如何将另一个模块中的变量发送给函数?
- java - 在类型 [com.modelimpl.Modelmvcimpl] 上找不到属性 [fname]
- java - 尝试通过 JSON 查询从 openweathermap 获取数据时出现 FileNotFoundException
- excel - 直到循环执行缓慢 - 偏移和选择的替代方案?