2011-04-29 95 views
2

我正在寻找一种方法来创建包含数据集的某些值的字符串变量,同时通过数据步骤。SAS变量级联通过数据步骤

实施例的数据集work.test:

AddToStringYN Value 
    Y   One 
    Y   Two 
    N   Three 
    Y   Four 
    N   Five 

所以在结束时,变量将如下所示:OneTwoFour(或甚至更好FourTwoOne)。 这看起来很简单,但我似乎无法找到办法。 我也试图与宏观变量工作是这样的:

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar',"&stringvar" || strip(value)); 
    end; 
Run; 

但是这给:

GLOBAL STRINGVAR Four 

所以我只得到了最后一个值。我明白这一定是因为我对这个宏观设施的误解,但我不明白为什么只有变量的最后一个值。 我以为只是最后一次symput被称为是实际执行或东西,但后来当我的代码调整为:

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar'||strip(value),"&stringvar" || strip(value)); 
    end; 
Run; 

那我让他们都:

GLOBAL STRINGVARONE One 
GLOBAL STRINGVARTWO Two 
GLOBAL STRINGVARFOUR Four 

所以我最后的猜测是,通过数据步骤,'调用symput ...'行实际上被添加到宏处理器,其中“& stringvar”已被替换,并且仅在最终语句被全部执行之后。
这是一个很好的假设还是存在另一种解释? 回到原来的问题:是否有一个简单的方法来实现这一点(具有所需的变量)?

回答

2

问候 似乎很简单,这里是我的解决方案:

data a; 
set test end=eof; 
length cat $100.; 
retain cat; 
if AddToStringYN = "Y" then do; 
    cat=trim(left(cat))||trim(left(value)); 
end; 
if eof then do; 
    call symput("VAR",cat); 
    output; 
end; 
run; 

%put VAR=&VAR; 

在这个例子中,你必须在列“CAT”的数据集的变量的级联和你有一个macrovariable VAR与同样的名单

+0

完善!我记得尝试使用这样的结构(保留和可变重用的组合),但它不起作用。现在还找不到什么不同,但它工作!确实很简单......如果你知道在哪里看;) 谢谢! (关于附加问题的任何想法,如果我的逻辑是正确的宏变量?) – Yoh 2011-04-29 11:07:10

+1

另外,尝试用cat(),catt(),cats(),catx()函数替换trim(left() 。它们非常灵活,更易于使用,并为您自动进行类型转换!可用SAS9以上... – 2011-04-29 19:40:29

+0

@Rob将调查,使用剥离()现在... – Yoh 2011-05-02 12:43:48

5

以下是我对your identical question on RunSubmit.com的回答。我认为你和@Fabio可能会过度设计解决方案,它不需要任何迭代数据步骤代码...

首先,简单的方法来做你想做的事就像这样:

proc sql; 
    select Value into :StringVar separated by '' 
    from work.test 
    where AddToStringYN='Y' 
    ; 
quit; 

在这里,你可以采取与SAS/MACRO的SQL接口的优势,使用select into语法。您甚至可以添加order by子句以获得您要查找的特定订单。第二,既然你已经发现了SAS宏的工作方式,并且你很想理解它:在你的第一个例子中,编译器在执行你的代码之前做的第一件事就是解析&stringvar的值,在那一点上是空的。所以在编译之后,用这个标记代替,你的代码看起来像这样对SAS ...

%let stringvar=; 
Data _null_; 
    set work.test; 
    if AddToStringYN = "Y" then do; 
    call symput('stringvar',"" || strip(value)); 
    end; 
Run; 

...那么SAS继续并运行该代码(这恰好是有效的代码,但是将空字符串连接到某个东西的开头)。并且由于数据步骤的工作方式,数据步骤的每次迭代实际上将取代StringVar的值,这就是为什么在数据步骤结束时,剩下的是读入的最后一个值。

+0

看到你的答案RunSubmit,没有时间回复yet.First非常感谢,尤其是关于SAS宏。事实上,我一直在考虑它的工作方式,解决宏观变量只发生一次,而不是数据步骤的每一次迭代。 关于proc sql的使用:我总是学习使用SAS代码优先于SQL(即处理时间)。我不知道这个例子是否支持这个例子。 – Yoh 2011-05-02 13:22:24

+1

@Yohsoog:SAS数据步骤代码与PROC SQL的性能没有严格的规则 - 哪一个更快取决于各种因素。您可以随时试用这两种解决方案,并查看日志,以查看这种情况下最快的数据。但也有其他一些考虑因素,例如代码可读性,可维护性,对其他人的清晰度,编码标准等。至于我,我会倾向于使用PROC SQL方法,除非您还在其中做了很多其他的东西数据步骤,使得I/O值得获得结果。 – sasfrog 2011-05-02 22:07:19

+0

是的,在这种情况下,我在数据步骤中做了很多其他的事情。数据步骤实际上循环遍历一个生成完整xml的表。而且我在这里放置的字符串在同一个数据步骤中的其他地方也会被分开,所以使用PROC SQL方法甚至是不可能的。但是,为了可读性等考虑,这是一件好事。 – Yoh 2011-05-03 07:48:04