2013-07-06 195 views
0

我有一个名为coaches_assistants的SAS数据集,其结构如下。每TeamID总是只有两条记录。从SAS中的多个记录创建单个记录

TeamID  Team_City CoachCode 
123  Durham  Head_242 
123  Durham  Assistant_876 
124  London  Head_876 
124  London  Assistant_922 
125  Bath   Head_667 
125  Bath   Assistant_786 
126  Dover  Head_544 
126  Dover  Assistant_978 
...  ...   .... 

我想如何处理此要做的是创建一个数据集有一个额外的字段名为AssistantCode,并使它看起来像:

TeamID  Team_City HeadCode AssistantCode 
123  Durham  242  876 
124  London  876  922 
125  Bath   667  786 
126  Dover  544  978 
...  ...   ...  ... 

如果可能的话,我愿意做的这在一个单独的DATA步骤中(尽管我知道我可能首先需要一个PROC SORT步骤)。我知道如何用python或ruby或任何传统的脚本语言来做到这一点,但我不知道如何在SAS中做到这一点。

这样做的最好方法是什么?

回答

1

这里有两个可能的解决方案(一个使用的请求数据的步骤和另一使用PROC SQL):

data have; 
    length TeamID $3 Team_City CoachCode $20; 
    input TeamID $ Team_City $ CoachCode $; 
    datalines; 
123  Durham  Head_242 
123  Durham  Assistant_876 
124  London  Head_876 
124  London  Assistant_922 
125  Bath   Head_667 
125  Bath   Assistant_786 
126  Dover  Head_544 
126  Dover  Assistant_978 
run; 

/* A data step solution */ 
proc sort data=have; 
    by TeamID; 
run; 

data want1(keep=TeamID Team_City HeadCode AssistantCode); 
    /* Define all variables, retain the new ones */ 
    length TeamID $3 Team_City $20 HeadCode $3 AssistantCode $3; 
    retain HeadCode AssistantCode; 
    set have; 
     by TeamID; 
    if CoachCode =: 'Head' 
     then HeadCode = substr(CoachCode,6,3); 
     else AssistantCode = substr(CoachCode,11,3); 
    if last.TeamID; 
run; 

/* An SQL solution */ 
proc sql noprint; 
    create table want2 as 
    select TeamID 
     , max(Team_City) as Team_City 
     , max(CASE WHEN CoachCode LIKE 'Head%' 
        THEN substr(CoachCode,6,3) ELSE ' ' 
       END) LENGTH=3 as HeadCode 
     , max(CASE WHEN CoachCode LIKE 'Assistant%' 
        THEN substr(CoachCode,11,3) ELSE ' ' 
       END) LENGTH=3 as AssistantCode 
    from have 
    group by TeamID; 
quit; 

PROC SQL有没有要求你提前对数据进行排序的优势。

+0

感谢您的详细信息。我采用第一种方法,它像一个魅力。我还没有深入研究SAS SQL,所以稍后我会在有机会的时候看看它。 – Clay

+0

在第一个代码示例中,“IF LAST.TeamID”是做什么的? – Clay

+1

在数据步骤处理中使用“BY”语句时,会自动创建特殊变量以协助处理。为语句中列出的每个变量创建两个“点”变量:“FIRST.variable”和“LAST.variable”,它们标识组中obs的相对位置。 '如果LAST.TeamID;'是一个“subsetting-IF”语句,用于每个TeamID只输出一个obs。 – BellevueBob

0

这里假设你已经按teamID对数据进行了排序,并且总教练总是来到助理面前。警告:未经测试(我真的需要重新获得访问SAS ....)

data want (drop=nc coachcode); 
    set have; 
    length headcode assistantcode $3; 
    retain headcode; 
    by teamid; 
    nc = length(coachcode); 
    if substr(coachcode, 1, 4) = 'Head' then 
     headcode = substr(coachcode, nc-2, nc); 
    else 
     assistantcode = substr(coachcode, nc-2, nc); 
    if last.teamid; 
run; 
+1

SCAN可能比子串更好:) – Joe

+0

@Joe谢谢,忘了那个。 –

2

虽然可以在一个datastep做,我通常发现,这类问题在PROC TRANSPOSE是更好的服务。用这种方式减少手动编码,为新事物提供更大的灵活性(比如说出现了一个新的“HeadAssistant”值,这会立即起作用)。

data have; 
length coachcode $25; 
input TeamID  Team_City $ CoachCode $; 
datalines; 
123  Durham  Head_242 
123  Durham  Assistant_876 
124  London  Head_876 
124  London  Assistant_922 
125  Bath   Head_667 
125  Bath   Assistant_786 
126  Dover  Head_544 
126  Dover  Assistant_978 
;;;; 
run; 

data have_t; 
set have; 
id=scan(coachcode,1,'_'); 
val = scan(coachcode,2,'_'); 
keep teamId team_city id val; 
run; 

proc transpose data=have_t out=want(drop=_name_); 
by teamID team_city; 
id id; 
var val; 
run; 
+0

我喜欢这看起来很干净,但是当我试图用我的数据集(有120,000多个观察值)运行它时,出于某种原因,创建了“不希望”表。我稍后再试。谢谢! – Clay