从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;