BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
Geo-
Quartz | Level 8

Anyone has SAS macro to create tables according to a column values?

Column id has 3 values (a,b,c),and create thress tables by this column.

original: 
idspendlend
a10.10.5
a5.57
b1.22
c36
b63.1
   
id_a:  
idspendlend
a10.10.5
a5.57
   
id_b:  
idspendlend
b1.22
b63.1
   
id_c:  
idspendlend
c36
1 ACCEPTED SOLUTION

Accepted Solutions
ChrisNZ
Tourmaline | Level 20

It's better to have only one data step, like:

%macro test;
  %local i out;
  data %do i = 1 %to &sqlobs;  _%scan(&val,&i) %end;;
    set have;
    %do i = 1 %to &sqlobs; 
      %let out=%scan(&val,&i);
      if id="&out" then output _&out. ;
    %end;
  run;
%mend;

%test;

But why? Just read a subset of the main table as needed.

It is seldom justified to do what you are attempting.

 

View solution in original post

5 REPLIES 5
Jagadishkatam
Amethyst | Level 16
data have;
infile cards dlm='09'x;
input id$	spend	lend;
cards;
a	10.1	0.5
a	5.5	7
b	1.2	2
c	3	6
b	6	3.1
;

proc sql;
select distinct id into : val separated by ' ' from have;
quit;
%put &sqlobs;


%macro test;
%do i = 1 %to &sqlobs;
%let outs=%scan(&val,&i);
data &outs;
set have;
if id="&outs";
run;
%end;
%mend;

%test;
Thanks,
Jag
ChrisNZ
Tourmaline | Level 20

It's better to have only one data step, like:

%macro test;
  %local i out;
  data %do i = 1 %to &sqlobs;  _%scan(&val,&i) %end;;
    set have;
    %do i = 1 %to &sqlobs; 
      %let out=%scan(&val,&i);
      if id="&out" then output _&out. ;
    %end;
  run;
%mend;

%test;

But why? Just read a subset of the main table as needed.

It is seldom justified to do what you are attempting.

 

Jagadishkatam
Amethyst | Level 16

by call execute

 

data have;
infile cards dlm='09'x;
input id$	spend	lend;
cards;
a	10.1	0.5
a	5.5	7
b	1.2	2
c	3	6
b	6	3.1
;

proc sort data=have out=distinct(keep=id) nodupkey;
by id;
run;

data _null_;
set distinct;
call execute("data "||id||";set have;if id='"||id||"';output "||id||"; run;");
run;
Thanks,
Jag
mkeintz
PROC Star

If you know in advance all the expected values of id, then it's very direct:

data have;
  input id :$1. spend lend;
datalines;
a 10.1 0.5
a 5.5 7
b 1.2 2
c 3 6
b 6 3.1
run;
data 
  id_a (where=(id='a'))
  id_b (where=(id='b'))
  id_c (where=(id='c'));
  set have;
run;

 

But if you don't know the value in advance, you'll need a couple of hash objects:

 


data _null_;  
  set have end=end_of_have;
  if _n_=1 then do;
    declare hash h;
    declare hash hoh();
      hoh.definekey('id');
      hoh.definedata('id','h');
      hoh.definedone();
    declare hiter i ('hoh');
  end;
  if hoh.find()^=0 then do;
    h=_new_ hash (ordered:'a');
      h.definekey('_n_');
      h.definedata('id','spend','lend');
      h.definedone();
    hoh.add();
  end;
  h.add();
  if end_of_have then do rc=i.first() by 0 while (rc=0);
    length dsname $100;
    dsname=cats('id_',id);
    h.output(dataset:trim(dsname));
    rc=i.next();
  end;
run;

 

This program builds a hash object (always called h) for each unique value of id.  The list of id values is tracked by the hash object hoh (for hash-of-hashes).

 

When an incoming record brings a value of id not yet in hoh (hoh.find()^=0), then (1) a new instance of hash object h is instantiated, and (2) a new item is added to hoh, containing id, and a pointer to the associated instance of h.  If the id is already in hoh then the hoh.find() method b make h point to the associated h.

 

Then the record is added to hash h.

 

At the end of the have dataset, iterate through hoh, retrieving each unique id one-at-a-time, and output the corresponding h to a dynamically named data set.

 

There will be a quiz in the morning.  It will probably be worth your while to learn some rudimentary processes for using hash object.

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

--------------------------
Reeza
Super User

Use FILEVAR To control the output file name and PUT to place the data in the csv file. 

 


@Geo- wrote:

Anyone has SAS macro to create tables according to a column values?

Column id has 3 values (a,b,c),and create thress tables by this column.

original:  
id spend lend
a 10.1 0.5
a 5.5 7
b 1.2 2
c 3 6
b 6 3.1
     
id_a:    
id spend lend
a 10.1 0.5
a 5.5 7
     
id_b:    
id spend lend
b 1.2 2
b 6 3.1
     
id_c:    
id spend lend
c 3 6

 

hackathon24-white-horiz.png

2025 SAS Hackathon: There is still time!

Good news: We've extended SAS Hackathon registration until Sept. 12, so you still have time to be part of our biggest event yet – our five-year anniversary!

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.

SAS Training: Just a Click Away

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

Browse our catalog!

Discussion stats
  • 5 replies
  • 2146 views
  • 1 like
  • 5 in conversation