I have a dataset of policies that sometimes have multiple IDs associated with them. Instead of having multiple rows for each policy I want to add additional columns to store that information side by side. How would I go about doing this?
Current Dataset Example:
| Policy | ID | Percent |
| 12345 | 12 | 5% |
| 12345 | 15 | 5% |
| 2346 | 23 | 6% |
| 2346 | 24 | 7% |
| 15678 | 30 | 5% |
Goal Dataset Example:
| Policy | ID1 | Percent1 | ID2 | Percent2 |
| 12345 | 12 | 5% | 15 | 5% |
| 2346 | 23 | 6% | 24 | 7% |
| 15678 | 30 | 5% |
Or try MERGE skill proposed by me ,Matt, Arthur.T .
http://support.sas.com/resources/papers/proceedings15/2785-2015.pdf
data have;
input Policy ID Percent :percent.;
format percent percent5.;
cards;
12345 12 5%
12345 15 5%
2346 23 6%
2346 24 7%
15678 30 5%
;
data temp(index=(policy));
set have;
by Policy notsorted;
if first.Policy then n=0;
n+1;
run;
proc freq data=temp noprint;
table n/out=key;
run;
data _null_;
set key end=last;
if _n_=1 then call execute('data want; merge ');
call execute(catt('temp(where=(n=',n,') rename=(id=id_',n,' percent=percent_',n,'))'));
if last then call execute(';by Policy;drop n;run;');
run;
proc transpose would be a tool of my choice here is a good link to fit your needs and help you understand how transpose works
https://stats.idre.ucla.edu/sas/modules/how-to-reshape-data-long-to-wide-using-proc-transpose/
Ok @tbs I will update and give you the code:
data have;
input Policy ID Percent $;
cards;
12345 12 5%
12345 15 5%
2346 23 6%
2346 24 7%
15678 30 5%
;
proc transpose data=have out=want1(drop=_name_) prefix=ID;
by Policy notsorted;
var id;
run;
proc sort data=want1;
by policy;
run;
proc transpose data=have out=want2(drop=_name_) prefix=percent;
by Policy notsorted;
var percent;
run;
proc sort data=want2;
by policy;
run;
data wanted;
merge want1 want2;
by policy;
run;
data have;
input Policy ID Percent :percent.;
format percent percent5.;
cards;
12345 12 5%
12345 15 5%
2346 23 6%
2346 24 7%
15678 30 5%
;
proc sql;
select max(c) into :n trimmed
from (select policy, count(id) as c from have group by policy);
quit;
%put &n;
data want;
do _n_=1 by 1 until(last.policy);
set have;
by policy notsorted;
array i(*) id1-id&n ;
array p(*) percent1-percent&n ;
i(_n_)=id;
p(_n_)=percent;
end;
drop id percent;
run;
data have;
input Policy ID Percent :percent.;
format percent percent5.;
cards;
12345 12 5%
12345 15 5%
2346 23 6%
2346 24 7%
15678 30 5%
;
proc sql;
select max(c) into :n trimmed
from (select policy, count(id) as c from have group by policy);
quit;
%put &n;
proc summary nway data=have missing;
class policy;
output
out = want(drop=_type_ _freq_)
idgroup(out[&n](id percent)=)
;
run;
Or try MERGE skill proposed by me ,Matt, Arthur.T .
http://support.sas.com/resources/papers/proceedings15/2785-2015.pdf
data have;
input Policy ID Percent :percent.;
format percent percent5.;
cards;
12345 12 5%
12345 15 5%
2346 23 6%
2346 24 7%
15678 30 5%
;
data temp(index=(policy));
set have;
by Policy notsorted;
if first.Policy then n=0;
n+1;
run;
proc freq data=temp noprint;
table n/out=key;
run;
data _null_;
set key end=last;
if _n_=1 then call execute('data want; merge ');
call execute(catt('temp(where=(n=',n,') rename=(id=id_',n,' percent=percent_',n,'))'));
if last then call execute(';by Policy;drop n;run;');
run;
Thanks for the help! The merge skill worked perfect as I ended up having multiple variables.
April 27 – 30 | Gaylord Texan | Grapevine, Texas
Walk in ready to learn. Walk out ready to deliver. This is the data and AI conference you can't afford to miss.
Register now and lock in 2025 pricing—just $495!
SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.
Find more tutorials on the SAS Users YouTube channel.