BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Moraes86
Obsidian | Level 7

Hi guys,

 

I am trying to move the values from the column "lot" to 3 columns A, B and C, according to respective category (A, B or C)

 

The second table is my goalThe second table is my goal

 

You can see the image below with 2 tables.  The second table is what I am trying to reach out, because I would like to move variable from column lot to category A, B or C.

 

Thanks guys,

 

Daniel

1 ACCEPTED SOLUTION

Accepted Solutions
sbxkoenk
SAS Super FREQ

Hello,

Very strange transpose, but OK ;-).

Please always provide your 'HAVE' data as a datastep with cards (datalines).

You get much more responses then!!

Code below works but better, more performant and more elegant code, is certainly possible.

data have;
 Length Head $ 20 Lot $ 10;
 infile cards delimiter='|';
 input Head $ Lot $ A B C;
 total=SUM(A,B,C);
 cards;
S001, S012, S013 |R8091120 |. |. |2
S001, S012, S013 |Y0661220 |. |. |2
S003             |P8690321 |1 |. |.
S004             |P3030321 |2 |. |.
S004             |P3440221 |2 |. |.
;
run;

data want(drop=Aold Bold Cold);
 set have(rename=(A=Aold B=Bold C=Cold));
 if      Aold ne . then A=Lot;
 else if Bold ne . then B=Lot;
 else if Cold ne . then C=Lot;
run;

data want(drop=Aold Bold Cold Lot lagHead);
 LENGTH Head $ 20 A $ 50 B $ 50 C $ 50;
 set want(rename=(A=Aold B=Bold C=Cold));
 retain A B C;
 lagHead=lag(Head);
 by Head;
 if first.Head then do; A=Aold; B=Bold; C=Cold; end;
 if NOT first.Head AND Head=lagHead then do; 
  A=strip(A)||','||strip(Aold); if A=',' then A='';
  B=strip(B)||','||strip(Bold); if B=',' then B='';
  C=strip(C)||','||strip(Cold); if C=',' then C='';
 end;
 if last.Head then output;
run;
/* end of program */

Cheers,

Koen

View solution in original post

4 REPLIES 4
sbxkoenk
SAS Super FREQ

Hello,

Very strange transpose, but OK ;-).

Please always provide your 'HAVE' data as a datastep with cards (datalines).

You get much more responses then!!

Code below works but better, more performant and more elegant code, is certainly possible.

data have;
 Length Head $ 20 Lot $ 10;
 infile cards delimiter='|';
 input Head $ Lot $ A B C;
 total=SUM(A,B,C);
 cards;
S001, S012, S013 |R8091120 |. |. |2
S001, S012, S013 |Y0661220 |. |. |2
S003             |P8690321 |1 |. |.
S004             |P3030321 |2 |. |.
S004             |P3440221 |2 |. |.
;
run;

data want(drop=Aold Bold Cold);
 set have(rename=(A=Aold B=Bold C=Cold));
 if      Aold ne . then A=Lot;
 else if Bold ne . then B=Lot;
 else if Cold ne . then C=Lot;
run;

data want(drop=Aold Bold Cold Lot lagHead);
 LENGTH Head $ 20 A $ 50 B $ 50 C $ 50;
 set want(rename=(A=Aold B=Bold C=Cold));
 retain A B C;
 lagHead=lag(Head);
 by Head;
 if first.Head then do; A=Aold; B=Bold; C=Cold; end;
 if NOT first.Head AND Head=lagHead then do; 
  A=strip(A)||','||strip(Aold); if A=',' then A='';
  B=strip(B)||','||strip(Bold); if B=',' then B='';
  C=strip(C)||','||strip(Cold); if C=',' then C='';
 end;
 if last.Head then output;
run;
/* end of program */

Cheers,

Koen

Tom
Super User Tom
Super User

It is not clear what TOTAL means in your example output.  If I take the MAX over all A,B,C for all observations for HEAD I get the same number you reported for that sample data.

You need to make NEW variables since the old A,B,C are numeric and the new A,B,C are character.  Make them long enough to hold all possible lists.

So if the data is sorted by HEAD it is pretty straight forward.  For only three variables arrays might be overkill but here is an example.

data want ;
   do until (last.head);
     set have ;
     by head ;
     array _num a b c ;
     array _ch $100 _a _b _c ;
     do i=1 to dim(_num);
       if not missing(_num[i]) then do;
         _ch[i]=catx(', ',_ch[i],lot);
         total = max(total,_num[i]);
       end;
     end;
   end;
   drop i a b c lot ;
   rename _a=A _b=B _c=C ;
run;

Results:

Obs    Head                A                     B            C             total

 1     S001, S012, S013                               R8091120, Y0661220      2
 2     S003                P8690321                                           1
 3     S004                P3030321, P3440221                                 2

Moraes86
Obsidian | Level 7

Thanks you soo much for this code. 

 

Moraes86
Obsidian | Level 7

Thank you so much for this code. 

It worked and it will help me a lot.

Daniel

 

sas-innovate-2024.png

Available on demand!

Missed SAS Innovate Las Vegas? Watch all the action for free! View the keynotes, general sessions and 22 breakouts on demand.

 

Register now!

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.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 4 replies
  • 627 views
  • 0 likes
  • 3 in conversation