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

Hi all,

 

I have a specific question that is not easy to google. Most certainly someone has already asked it, so apologies for asking it twice.

 

I have a dataset that looks like this:

 

Client Code

1 A

1 B

2 A

3 A

3 C

3 D

4 A

5 A

5 B

...

 

For every Client number I have the code A, so I want to make my dataset a little smaller and easier to handle by creating indicators if a client also has the codes B, C and/or D.

 

So, my final dataset (after removing the redundant rows) looks like this:

 

Client Code ind_B ind_C ind_D

1 A 1 0 0

2 A 0 0 0

3 A 0 1 1

4 A 0 0 0

5 A 1 0 0

...

 

I succeeded to do this by creating 2 datasets and joining them, but that is not time and memory efficient. I prefer not to loop over all clients and I'm convinced there is a better way to do this, I just cannot come up with it.

 

Can anyone help me?

1 ACCEPTED SOLUTION

Accepted Solutions
Ksharp
Super User
data have;
input client code $;
cards;
1 A
1 B
2 A
3 A
3 C
3 D
4 A
5 A
5 B
;
run;
proc sql;
select client,'A' as code,
 sum(code='B') as B,sum(code='C') as C,sum(code='D') as D 
  from have
   group by client;
quit;

View solution in original post

9 REPLIES 9
RW9
Diamond | Level 26 RW9
Diamond | Level 26

TBH I would strongly suspect that your want dataset here would be larger than the have dataset.  In the have dataset you are only capturing data where it appears, in the want data you are creating empty data items where there is no data.  For example:
Client 1 has two datapoints, a and b, but in the want dataset the same client has 3 datapoints, b, c, and d two of which are redundant.  Unless there is a very good reason (and I can't see one) to have that want structure, I would stick with your first, and filter out where code="A" if they all have it, as that is not needed at all.  This would effecively shrink your have to 4*2 fields which is far smaller than your want of 5*5.  

 

Robs234
Fluorite | Level 6

You are right in my example.

 

I did not mention though that each row contains much more columns with client information.

These columns are independent of the code, so the dataset contains a lot of duplicative information.

Therefore it is more efficient to create an indicator such that I can remove the rows that have not code A.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

Sorry, you going to have to clarify, test data/required output etc.  This:

"I can remove the rows that have not code A"

To me resolves as:

proc sql;
  create table want as
select *
from have where client not in (select distinct client from have where code="A"); quit;

Ie create a copy of the data with only clients who have an "A" record.

Kurt_Bremser
Super User

See this:

data have;
input client code $;
cards;
1 A
1 B
2 A
3 A
3 C
3 D
4 A
5 A
5 B
;
run;

data int;
set have (where=(code ne 'A')) ;
val = 1;
run;

proc transpose
  data=int
  out=codes (drop=_name_)
  prefix=ind_
;
by client;
id code;
var val;
run;

data want;
merge
  have (
    in=a
    where=(code = 'A')
  )
  codes
;
by client;
if a;
run;

proc print data=want noobs;
run;
Robs234
Fluorite | Level 6
Thank you, this gives the output I needed, although I prefer Ksharp's answer
Ksharp
Super User
data have;
input client code $;
cards;
1 A
1 B
2 A
3 A
3 C
3 D
4 A
5 A
5 B
;
run;
proc sql;
select client,'A' as code,
 sum(code='B') as B,sum(code='C') as C,sum(code='D') as D 
  from have
   group by client;
quit;
Robs234
Fluorite | Level 6
Thanks this is exactly what I wanted
data_null__
Jade | Level 19

Seems like a method works without knowing the values of CODE would be useful.

 

data have;
   input client code :$1. @@;
   cards;
1 A 1 B 2 A 3 A 3 C 3 D 4 A 5 A 5 B
;;;;
   run;
proc transreg data=have design;
   id client;
   model class(code/zero=none CPREFIX=0);
   output out=design(drop=Int: _:);
   run;
proc print;
   run;
proc means noprint nway;
   class client;
   output out=want(drop=_:) sum=;
   run;
proc print;
   run;

Capture.PNG

 

Ksharp
Super User

John King,

Long time no see.

Sure . That would be easy. 

1) PROC FREQ to get all these levels.

2)CALL EXECUTE() to make it happen .

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

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
  • 9 replies
  • 1092 views
  • 1 like
  • 5 in conversation