BookmarkSubscribeRSS Feed
Feefee
Fluorite | Level 6

Hi, 

 

I have dataset that looks like this: 

 

Locker IDLocationsPerson APerson BPerson CPerson A CodePerson B CodePerson C Code
101Hampersmith, SilvershineSam CopewellAmy BakerJohn Aston123A234B345C
102Coleridge, BrisbakeClaude TremaineMarissa Carter 567D678E 
103Waterloop, SturreyBrian AmbleCharlie SpringwaterMandy Smith012G134H245J

 

I want to split this data set into multiple rows by the persons like so:

 

Locker IDLocationsPersonPerson Code
101Hampersmith, SilvershineSam Copewell123A
101 Hampersmith, SilvershineAmy Baker234B
101Hampersmith, SilvershineJohn Aston345C
102Coleridge, BrisbakeClaude Tremaine567D
102Coleridge, BrisbakeMarissa Carter678E
103Waterloop, SturreyBrian Amble012G
103Waterloop, SturreyCharlie Springwater134H
103Waterloop, SturreyMandy Smith245J

 

Please can you help, all numbers/letters are just placeholders so avoiding code that specifies any of that.

 

Appreciate your help!

5 REPLIES 5
PaigeMiller
Diamond | Level 26
/* UNTESTED CODE */

data want;
    set have;
    person=personA;
    personcode=personAcode;
    output;
    person=personB;
    personcode=personBcode;
    output;
    person=personC;
    personcode=personCcode;
    output;
    keep lockerid locations person personcode;
run;

 

 

Please from now on provide data as working SAS data step code (examples and instructions). Also, I'm sure you know this, but SAS data sets cannot have variables with spaces in the variable name.

--
Paige Miller
data_null__
Jade | Level 19

You could use two calls to proc transpose and is pretty easy to extend to more variables.

 

data have;
   infile cards dsd dlm='09'x;
   input (Locker_ID	Locations	Person_A	Person_B	Person_C	Person_A_Code	Person_B_Code	Person_C_Code)(:$32.);
   cards;
101	Hampersmith, Silvershine	Sam Copewell	Amy Baker	John Aston	123A	234B	345C
102	Coleridge, Brisbake	Claude Tremaine	Marissa Carter	 	567D	678E	 
103	Waterloop, Sturrey	Brian Amble	Charlie Springwater	Mandy Smith	012G	134H	245J
;;;;
   run;

proc transpose data=have out=flip(where=(not missing(col1))) name=vname;
   by locker_id locations;
   var person:;
   run;
proc sort data=flip;
   by locker_id locations vname;
   run;
data flip;
   set flip;
   length _name_ $32;
   pid = first(scan(vname,2,'_'));
   if find(vname,'code','IT') then _name_ = 'Code';
   else _name_ = scan(vname,1,'_');
   run;
proc transpose data=flip out=flop(drop=_name_);
   by locker_id locations pid;
   var col1;
   id _name_;
   run; 

Capture.PNG

dxiao2017
Pyrite | Level 9

Hi @Feefee does this answer your question?

data personcd;
   input id location $5-26 person1 $28-42
         person2 $44-62 person3 $64-74 
         p1code $5. p2code $5. p3code $5.;
   datalines;
101 Hampersmith,Silershine Sam Copewell    Amy Baker           John Aston  123A 234B 345C
102 Coleridge,Brisbake     Claude Tremaine Marissa Carter                  567D 678E
103 Waterloop,Sturrey      Brian Amble     Charlie Springwater Mandy Smith 012G 134H 245J
;
run;
proc print data=personcd;run;
proc transpose data=personcd 
               out=name(rename=(col1=person)
                        drop=_name_);
   by id location;
   var person:;
run;
proc print data=name;run;
proc transpose data=personcd 
               out=code(rename=(col1=personcd)
                        drop=_name_);
   by id location;
   var p1code--p3code;
run;
proc print data=code;run;
data final;
   merge name code;
   if person^=' ';
run;
proc print data=final;run;

dxiao2017_0-1747928985533.png

dxiao2017_1-1747929097087.png

 

SAS help cars; we are cars; that is why my default image;
mkeintz
PROC Star

Probably a single DATA step is the simplest approach.  Generalizing a bit from @PaigeMiller, consider the use of arrays, as in:

 

data want (keep=locker_id locations person code);
  set have;
  array pers {*} person_a--person_c;
  array cods {*} person_a_code-- person_c_code;

  do i=1 to dim(pers);
    person=pers{i};
    code=cods{i};
    if person^=' ' then output;
  end;
run;

If you want to add a PID variable  (="A", or "B", or "C", etc.) as done by @data_null__ , you can make a minor tweak: 

 


data want (keep=locker_id locations person pid code);
  set have;
  array pers {*} person_a--person_c;
  array cods {*} person_a_code-- person_c_code;

  do i=1 to dim(pers);
    person=pers{i};
    pid=byte(i+64);   /*Byte(65)='A', Byte(66)='B', etc. */
    code=cods{i};
    if person^=' ' then output;
  end;
run;
--------------------------
The hash OUTPUT method will overwrite a SAS data set, but not append. That can be costly. Consider voting for Add a HASH object method which would append a hash object to an existing SAS data set

Would enabling PROC SORT to simultaneously output multiple datasets be useful? Then vote for
Allow PROC SORT to output multiple datasets

--------------------------
Kurt_Bremser
Super User

@Feefee wrote:

Hi, 

 

I have dataset that looks like this: 

 


No, you don't. SAS names can't have blanks or linefeeds in them. 

Please do ALWAYS post example data as working DATA step code with DATALINES.

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

How to Concatenate Values

Learn how use the CAT functions in SAS to join values from multiple variables into a single value.

Find more tutorials on the SAS Users YouTube channel.

SAS Training: Just a Click Away

 Ready to level-up your skills? Choose your own adventure.

Browse our catalog!

Discussion stats
  • 5 replies
  • 734 views
  • 4 likes
  • 6 in conversation