从SAS中的多个记录创建单个记录

从SAS中的多个记录创建单个记录,sas,datastep,Sas,Datastep,我有一个名为coach\u assistants的SAS数据集,其结构如下。每个TeamID始终只有两条记录 TeamID Team_City CoachCode 123 Durham Head_242 123 Durham Assistant_876 124 London Head_876 124 London Assistant_922 125 Bath

我有一个名为
coach\u assistants
的SAS数据集,其结构如下。每个
TeamID
始终只有两条记录

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
...        ...          ...        ...
如果可能的话,我希望在单个数据步骤中完成这项工作(尽管我认识到我可能首先需要一个PROC排序步骤)。我知道如何在python、ruby或任何传统脚本语言中实现,但我不知道如何在SAS中实现


最好的方法是什么?

这假设您已按
teamID
对数据进行了排序,并且主教练总是排在助理之前。警告:未经测试(我真的需要再次访问SAS…)


这假设您已经按照
teamID
对数据进行了排序,并且主教练总是排在助理之前。警告:未经测试(我真的需要再次访问SAS…)


虽然可以在一个数据步骤中完成,但我通常发现在PROC转置中更好地解决这类问题。这种方式减少了手工编码,对新事物有了更大的灵活性(比如说出现了一个新的值“HeadAssistant”,这会立即起作用)


虽然可以在一个数据步骤中完成,但我通常发现在PROC转置中更好地解决这类问题。这种方式减少了手工编码,对新事物有了更大的灵活性(比如说出现了一个新的值“HeadAssistant”,这会立即起作用)


以下是两种可能的解决方案(一种使用请求的数据步骤,另一种使用PROC-SQL):


PROC SQL的优点是不需要您事先对数据进行排序。

以下是两种可能的解决方案(一种是根据请求使用数据步骤,另一种是使用PROC SQL):


PROC SQL的优点是不需要您事先对数据进行排序。

扫描可能比子字符串更好:)@Joe谢谢,忘了那个。扫描可能比子字符串更好:)@Joe谢谢,忘了那个。谢谢详细信息。我采用了第一种方法,效果很好。我还没有深入研究过SAS SQL,所以有机会以后我会研究它。当在数据步处理中使用
BY
语句时,会自动创建特殊变量来辅助处理。为语句中列出的每个变量创建两个“点”变量:
FIRST.variable
LAST.variable
,用于标识obs在组中的相对位置<代码>如果LAST.TeamID是一个“subsetting IF”语句,用于每个TeamID只输出一个obs。感谢您的解释。我不知道第一次和最后一次。谢谢你提供的详细信息。我采用了第一种方法,效果很好。我还没有深入研究过SAS SQL,所以有机会以后我会研究它。当在数据步处理中使用
BY
语句时,会自动创建特殊变量来辅助处理。为语句中列出的每个变量创建两个“点”变量:
FIRST.variable
LAST.variable
,用于标识obs在组中的相对位置<代码>如果LAST.TeamID是一个“subsetting IF”语句,用于每个TeamID只输出一个obs。感谢您的解释。我不知道
第一个
最后一个
。我喜欢它看起来有多干净,但是当我试图用我的数据集(120000多个观察值)运行它时,出于某种原因,
想要的
表没有任何列。我稍后再试一次。谢谢我喜欢它看起来有多干净,但是当我试图用我的数据集(120000多个观察值)运行它时,出于某种原因,
want
表是在没有任何列的情况下创建的。我稍后再试一次。谢谢
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;
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;
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;