BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
BrahmanandaRao
Lapis Lazuli | Level 10
DATA DSN;
INPUT SEX$;
DATALINES;
F
F
F
F
M
M
M
M
;
RUN;

I want output

F

M

F

M

F

M

F

M

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
novinosrin
Tourmaline | Level 20


DATA DSN;
INPUT SEX$;
DATALINES;
F
F
F
F
M
M
M
M
;
RUN;


data _null_;
if _n_=1 then do;
   dcl hash H (ordered: "A",multidata:'y') ;
   h.definekey  ("_n_") ;
   h.definedata ("sex") ;
   h.definedone () ;
end;
do _n_=1 by 1 until(last.sex);
 set dsn end=z;
 by sex;
 h.add();
 output;
end;
if z ;
h.output(dataset:'want');
run;

View solution in original post

11 REPLIES 11
Patrick
Opal | Level 21

Below will work for your sample data but be aware that the SAS data step will stop as soon as one of the groups doesn't have any further observations (=if the groups are not equal some source observations will not be written to target). 

data want;
  set have(where=(sex='F'));
  output;
  set have(where=(sex='M'));
  output;
run;

Is that o.k. or do you need an approach with writes all the source obs to target?

BrahmanandaRao
Lapis Lazuli | Level 10

Thank you

Patrick

hashman
Ammonite | Level 13

@Patrick:

Another way in a somewhat similar vein:

data have ;                                                                   
  input (name sex) ($) ;                                                      
  cards ;                                                                     
Alice  F                                                                      
Beth   F                                                                      
Carol  F                                                                      
Doris  F                                                                      
Alex   M                                                                      
Bob    M                                                                      
Cary   M                                                                      
Doug   M                                                                      
;                                                                             
run ;                                                                         
                                                                              
data want (drop = _:) ;                                                       
  merge have (where=(sex="F")) have (where=(_s="M") rename=(name=_n sex=_s)) ;
  output ;                                                                    
  name = _n ;                                                                 
  sex  = _s ;                                                                 
  output ;                                                                    
run ;                                                                         

Output-wise, it's a little different from your double SET in that if some F or M has no counterpart, her/his record will be where it would be if the counterpart existed but with missing values.

 

Kind regards

Paul D.   

Ksharp
Super User
DATA DSN;
INPUT SEX$;
DATALINES;
F
F
F
F
M
M
M
M
;
RUN;
data F;
  set dsn(where=(sex='F'));
  n+1;
run;
data M;
  set dsn(where=(sex='M'));
  n+1;
run;
data want; 
 set F M;
 by n;
run;
BrahmanandaRao
Lapis Lazuli | Level 10

Thank You

Sharp

novinosrin
Tourmaline | Level 20


DATA DSN;
INPUT SEX$;
DATALINES;
F
F
F
F
M
M
M
M
;
RUN;


data _null_;
if _n_=1 then do;
   dcl hash H (ordered: "A",multidata:'y') ;
   h.definekey  ("_n_") ;
   h.definedata ("sex") ;
   h.definedone () ;
end;
do _n_=1 by 1 until(last.sex);
 set dsn end=z;
 by sex;
 h.add();
 output;
end;
if z ;
h.output(dataset:'want');
run;

Cynthia_sas
SAS Super FREQ

Hi:

  When you say "print" do you mean that you need a report? By making a "helper" variable to control ordering, you can create the data, then order as you want. PROC REPORT allows you to use the "helper" variable but hide it on the report, as shown in #1. Report #2 reveals the ROWORD helper variable value to control ordering:

roword.png

 

I added NAME to the fake data, so you could see that the reordering was done correctly when ROWORD was hidden.

 

The program is here:

DATA fakedata;
INPUT name $ SEX $;
DATALINES;
Anna F
Barb F
Cindy F
Diane F
Art M
Bob M
Carl M
Denis M
;
RUN;

data final;
  set fakedata;
  by sex;
  if first.sex then roword=0;
  roword+1;
run;

proc report data=final;
title '1) Use Helper Variable ROWORD to reorder report rows';
  column roword name sex;
  define roword / order noprint;
  define name / display;
  define sex / display;
run;
title;


proc report data=final;
title '2) See value of Helper Variable ROWORD';
  column roword name sex;
  define roword / order;
  define name / display;
  define sex / display;
run;
title;

 

Hope this helps provide an alternative approach.

Cynthia

FreelanceReinh
Jade | Level 19

Hi @BrahmanandaRao,

 

Here's another approach for an input dataset consisting of two blocks of equal size (irrespective of variable values):

data want;
do _n_=1 to n;
  p=ifn(_n_=1,1,p+n/2-(n-1)*mod(_n_,2));
  set dsn nobs=n point=p;
  output;
end;
stop;
run;

Feel free to use a suitable PUT statement (e.g. in conjunction with FILE PRINT in a DATA _NULL_ step) rather than OUTPUT in order to create printed output.

hashman
Ammonite | Level 13

@FreelanceReinh:

Love your p-arithmetic! 😉

 

Kind regards

Paul D. 

novinosrin
Tourmaline | Level 20
DATA DSN;
INPUT SEX$;
DATALINES;
F
F
F
F
M
M
M
M
;
RUN;


data want;
 dcl hash H (dataset:'dsn',ordered:'y') ;
 h.definekey  ("sex") ;
 h.definedata ("sex") ;
 h.definedone () ;
 dcl hiter hi('h');
do _n_=1 to n/2;
 do while(hi.next()=0);
  output;
 end;
end;
stop;
set dsn nobs=n;
run;

Patrick
Opal | Level 21

And just for fun as a total overkill below a hash of hashes approach. 

The code is largely based on what @PeterClemmensen  shared here: http://sasnrd.com/sas-hash-object-of-hash/

The source data doesn't need to be pre-sorted nor is it necessary to know the number of distinct values for sex in advance.

data have;
  input sex $;
  datalines;
f
f
f
f
m
m
x
m
m
x
;

data want(drop=_:);
  declare hash HoH();
  HoH.definekey ('sex');
  HoH.definedata('h','sex');
  HoH.definedone();
  declare hiter HoHiter("HoH");
  declare hash h;

  do until (eof);
    set have end=eof;

    if HoH.find() ne 0 then
      do;
        h=_new_ hash(dataset:'have(obs=0)', multidata:'Y');
        h.definekey('sex');
        h.definedata(all:'Y');
        h.definedone();
        HoH.add();
      end;

    h.add();
  end;

  do until(_itemsLeft=0);
    _itemsLeft=0;
    do while(HoHiter.next() = 0);
      if h.num_items>0 then
        do;
          h.find();
          h.removedup();
          if h.num_items>0 then _itemsLeft=1;
          output;
        end;
    end;
  end;
run;

proc print;
run;

Ready to join fellow brilliant minds for the SAS Hackathon?

Build your skills. Make connections. Enjoy creative freedom. Maybe change the world. Registration is now open through August 30th. Visit the SAS Hackathon homepage.

Register today!
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
  • 11 replies
  • 1601 views
  • 7 likes
  • 7 in conversation