String 是否可以根据SAS中全局变量的成员数创建字母字符串(用ands分隔)?
我希望构建一个系统,使用merge函数基于公共值合并数据集 然而,我知道有时我必须合并2个数据集,有时我必须合并20个数据集 因此,通用合并函数如下所示String 是否可以根据SAS中全局变量的成员数创建字母字符串(用ands分隔)?,string,merge,sas,global,String,Merge,Sas,Global,我希望构建一个系统,使用merge函数基于公共值合并数据集 然而,我知道有时我必须合并2个数据集,有时我必须合并20个数据集 因此,通用合并函数如下所示 DATA [data_set]; merge [loop over data to be merged] by [factors which I am merging by] if [a and b] format [sort order] run; 问题是,在if之后,[a和b]显然需要生成一个字符
DATA [data_set];
merge
[loop over data to be merged]
by [factors which I am merging by]
if [a and b]
format [sort order]
run;
问题是,在if之后,[a和b]显然需要生成一个字符串,其长度等于要合并的表的数量。如果我想合并2个表[a和b]很好,但是如果我想合并3个表,它必须是[a、b和c]
有没有一种方法可以让我生成一个字符串[a和b,…N],其中是基于全局变量的长度生成的
希望我的问题很清楚,我不能提供我正在使用的实际代码,因为它包含敏感信息。如果我遗漏了什么,我会尽力提供更多信息/回答问题
使用@Richard中的makedata函数
%let MergeData = X1 X2 X3 X4 X5 X6 X7 X8 X9 X10;
DATA X_COMB;
merge
%internalmacro1(
%nrstr(
#L1#;
)
,L1 = &MergeData.
);
by id;
if ; /* create a string based on %&MergeData length, of # and # and # ... where # = a,b,c,d */
run;
但是,如果最后一个if存在,我想知道%MergeData集中的项数,我想我需要创建一个数组,并将值转换为十六进制?“a b c”等必须有一些等效的十六进制值
问题是人们将添加和删除集合&MergeData中的项,因此我尝试创建的合并需要扩展到输入的数据集合的数量?对不起,我不能提供更多
罗西方法:
proc import
datafile = "FilePath\Alphabet.csv"
DBMS = csv
OUT = AlphabetConversion;
;
data desiredstatements;
set AlphabetConversion (obs=26); /*This limits the observations used*/
run;
proc sql;
select AlphabetConversion into :dynamiccode from desiredstatements separated by " and ";
quit;
%put &dynamiccode.; /*Check the log to see what you got and make sure it's the code you want */
DATA Merged_Data
merge
mydata1 (in=_mydata1) mydata2(in=_mydata2) mydata3 (in=_mydata3);
by ID;
if _mydata1 and _mydata2 and _mydata3;
昆汀方法:
proc import
datafile = "FilePath\Alphabet.csv"
DBMS = csv
OUT = AlphabetConversion;
;
data desiredstatements;
set AlphabetConversion (obs=26); /*This limits the observations used*/
run;
proc sql;
select AlphabetConversion into :dynamiccode from desiredstatements separated by " and ";
quit;
%put &dynamiccode.; /*Check the log to see what you got and make sure it's the code you want */
DATA Merged_Data
merge
mydata1 (in=_mydata1) mydata2(in=_mydata2) mydata3 (in=_mydata3);
by ID;
if _mydata1 and _mydata2 and _mydata3;
这种结构适合于指定所有输入的合并。我的问题是,我正在尝试编写一个宏,它有时会接受mydata1和mydata2,有时会接受mydata1-mydata20。我不知道如何制作if\u mydata1和\u mydata2_mydata20,当它有20个要合并的数据集时,以及_mydata1和_mydata2,当它只有两个数据集时。如果我理解了你的问题,以下内容是否达到了你的目的
%let ds_list = a b c d;
%let ds_and_ds = %sysfunc(tranwrd(&ds_list,%str( ),%str( and )));
%put ds_list = &ds_list;
%put ds_and_ds = &ds_and_ds;
如果没有,请给出一个数据集列表的示例,您希望在每个数据集之间插入“和”。也许您可以基于此数据编写一些示例代码
%macro makedata;
%local i;
data %do i = 1 %to 10; x&i(keep=id x&i) %end;;
do id = 1 to 42;
array x(10);
do _n_ = 1 to dim(x);
x(_n_) = id * 100 + _n_;
end;
output;
end;
run
%mend;
%makedata;
data want;
merge ... fill in the rest ...;
... fill in the rest ...
run;
您对我之前给您的代码的尝试已经接近尾声,但有一件关键的事情(除了我给您错误的SQL语句顺序-很抱歉,下面已修复)是您正在CSV中读取并假设它有标题,而我更希望在代码中定义变量。然后,当您应该在
proc SQL
中命名变量时,您正在命名数据集名称-请尝试以下操作:
/*File must have one letter pet row*/
%let file=\\hefce-sas\nuser\user\thomaro\SAS\Temp\Alphabet.csv;
data AlphabetConversion;
infile "&file."
delimiter=',' missover dsd;
format letter $1.;
input letter $;
run;
/*I've explicitly defined this so it runs but this needs to be dynamic - see below*/
%let numstatements = 5;
data desiredstatements;
set AlphabetConversion (obs=&numstatements.); /*This limits the observations used*/
run;
proc sql;
select letter into :dynamiccode separated by ' and ' from desiredstatements;
quit;
/*Check the log to see what you got and make sure it's the code you want */
%put &dynamiccode.;
这种构造通常对于动态创建代码非常有用
现在有一个动态定义numstatements
的问题-这应该基于代码顶部的行:
%let MergeData = X1 X2 X3 X4 X5 X6 X7 X8 X9 X10;
因此,我建议您需要一个计算单词的宏函数-没有这样的函数,但您可以使用%sysfunc()
,将普通函数countw
转换为宏函数-因此您需要用类似以下内容替换上面的%let
:
%let numstatements = %sysfunc(countw(&mergedata.));
%put The number of datasets to be merged is &numstatements.;
现在(如果我正确理解了您的问题),当您想使用不同数量的数据集运行代码时,您所需要做的就是更改代码顶部的
%let MergeData=
,然后就可以开始了。给定一组数据集,如:
data mydata1 ;
input id x1 ;
cards ;
1 10
2 20
3 30
;
data mydata2 ;
input id x2 ;
cards ;
1 100
3 300
;
data mydata3 ;
input id x3 ;
cards ;
1 1000
2 2000
3 3000
;
data all ;
merge
mydata1 (in=_mydata1)
mydata2 (in=_mydata2)
mydata3 (in=_mydata3)
;
by id ;
if _mydata1 and _mydata2 and _mydata3 ;
run ;
您可以将它们合并在一起,只保留三个数据集之间匹配的记录,如:
data mydata1 ;
input id x1 ;
cards ;
1 10
2 20
3 30
;
data mydata2 ;
input id x2 ;
cards ;
1 100
3 300
;
data mydata3 ;
input id x3 ;
cards ;
1 1000
2 2000
3 3000
;
data all ;
merge
mydata1 (in=_mydata1)
mydata2 (in=_mydata2)
mydata3 (in=_mydata3)
;
by id ;
if _mydata1 and _mydata2 and _mydata3 ;
run ;
如果您查看上述步骤,很明显有两个列表。merge语句上的数据集列表和IF语句上的变量列表。可以使用宏语言生成该步骤。调用宏时,将向其传递要合并的数据集列表。然后,宏将通过合并生成数据步骤
这是一个宏,它使用宏循环生成两个列表:
%macro innermerge
(data= /*space-delimited list of data sets to be merged*/
,by= /*space-delimited list of BY variables for merge*/
,out= /*output data set*/
)
;
%local i data_i ;
data &out ;
merge
%do i=1 %to %sysfunc(countw(&data,%str( ))) ;
%let data_i=%scan(&data,&i,%str( )) ;
&data_i (in=_&data_i)
%end ;
;
by &by ;
if
%do i=1 %to %sysfunc(countw(&data,%str( ))) ;
%let data_i=%scan(&data,&i,%str( )) ;
%if &i>1 %then %do ;
and
%end ;
_&data_i
%end ;
;
run ;
%mend;
使用类似于:
%innermerge
(data=mydata1 mydata2
,by=id
,out=want
)
MPRINT(INNERMERGE): data want ;
MPRINT(INNERMERGE): merge mydata1 (in=_mydata1) mydata2 (in=_mydata2) ;
MPRINT(INNERMERGE): by id ;
MPRINT(INNERMERGE): if _mydata1 and _mydata2 ;
MPRINT(INNERMERGE): run ;
NOTE: There were 3 observations read from the data set WORK.MYDATA1.
NOTE: There were 2 observations read from the data set WORK.MYDATA2.
NOTE: The data set WORK.WANT has 2 observations and 3 variables.
%innermerge
(data=mydata1 mydata2 mydata3
,by=id
,out=want
)
MPRINT(INNERMERGE): data want ;
MPRINT(INNERMERGE): merge mydata1 (in=_mydata1) mydata2 (in=_mydata2) mydata3 (in=_mydata3) ;
MPRINT(INNERMERGE): by id ;
MPRINT(INNERMERGE): if _mydata1 and _mydata2 and _mydata3 ;
MPRINT(INNERMERGE): run ;
NOTE: There were 3 observations read from the data set WORK.MYDATA1.
NOTE: There were 2 observations read from the data set WORK.MYDATA2.
NOTE: There were 3 observations read from the data set WORK.MYDATA3.
NOTE: The data set WORK.WANT has 2 observations and 4 variables.
您是否正在编写宏以通用方式执行此操作?如果是这样的话,请发布您迄今为止编写的宏代码,或者至少发布一个删除了任何敏感信息的最低版本。我打算编写一个宏,但我不确定应该从哪里开始。我是SAS的新手。我会在进展中发布更新,我想知道人们以前是否遇到过这个问题。您知道如何使用数据集选项
(in=flag var)
?正在合并的表中是否有a
和b
附属变量,或者它们是否应该是特定表中某一行正在处理的标志变量,因为基于by变量(即表正在参与by组),您可能试图过早地学习宏。最好先好好学习数据步代码。也就是说,我建议您展示一个所需数据步骤代码的示例,展示如何合并3个数据集。这听起来像是merge mydata1(in=\u mydata1)mydata2(in=\u mydata2)mydata3(in=\u mydata3);按身份证;如果"我的数据1和"我的数据2和"我的数据3,
如果您研究宏循环,应该直接编写一个宏,该宏接受数据集列表作为参数并生成该代码。注意:在这种情况下,使用in=\u mydata或just in=\i应该简化事情,而不是生成in=\u a。@昆廷试图在主要帖子中更好地解释我的问题。当我可以手动合并它们时,我知道如何合并,这是因为我需要一个数据步骤,该步骤将根据所需的任意数量的合并进行合并。(最多20个)试图更新主要帖子,以更清楚地解释我的目标?还是不知道怎么做我要找的绳子嗨,罗西,你能举个例子吗?假设我有3个数据集%let SampleSet=X1 X2 X3如何生成&dynamiccode。生产“a、b和c”?我觉得我错过了一步。a和b真的是你的情况吗?我确实错过了第一步(故意,