String 是否可以根据SAS中全局变量的成员数创建字母字符串(用ands分隔)?

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]显然需要生成一个字符

我希望构建一个系统,使用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]显然需要生成一个字符串,其长度等于要合并的表的数量。如果我想合并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真的是你的情况吗?我确实错过了第一步(故意,