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

 

Hey,

 

Have:

PatientID     Min_YearMo    Max_YearMo

A                     201711             201803

B                     201801            201803

 

Want:

PatientID     Min_YearMo    Max_YearMo

A                     201711             201803

A                     201712             201803

A                     201801             201803

A                     201802             201803

B                     201801             201803

B                     201802             201803

 

I want create new rows based on number of month difference between min and max yearmonths. 

Max_YearMo is always constant across all patient. 

 

Thanks, appreciate your help.

1 ACCEPTED SOLUTION

Accepted Solutions
hashman
Ammonite | Level 13

@Sujithpeta:

 

In SAS, storing dates as a YYYYMM number is highly deprecated for a variety of reasons. However, if this is what you have in your input data and if you want to keep it such on the way out, some on-the-fly transformation is needed to make them into SAS date values, or otherwise the INTNX function cannot operate properly:

data have ;                                                                                                                                      
  input patientid $ (min_yearmo max_yearmo) (:6.) ;                                                                                              
  cards ;                                                                                                                                        
A  201711  201803                                                                                                                                
B  201801  201803                                                                                                                                
;                                                                                                                                                
                                                                                                                                                 
data want (drop = _:) ;                                                                                                                          
  set have ;                                                                                                                                     
  _minym = input (put (min_yearmo, z6.), yymmn6.) ;                                                                                              
  do _n_ = 1 by 1 until (_minym = input (put (max_yearmo, z6.), yymmn6.)) ;                                                                      
    output ;                                                                                                                                     
    _minym = intnx ("mon", _minym, 1) ;                                                                                                          
    min_yearmo = input (put (_minym, yymmn6.), 6.) ;                                                                                             
  end ;                                                                                                                                          
run ;      

Kind regards

Paul D.

View solution in original post

8 REPLIES 8
hashman
Ammonite | Level 13

@Sujithpeta:

 

INTNX is your friend:

data have ;                                                                                                                                      
  input patientid $ (min_yearmo max_yearmo) (:yymmn6.) ;                                                                                         
  format m: yymmd7. ;                                                                                                                            
  cards ;                                                                                                                                        
A  201711  201803                                                                                                                                
B  201801  201803                                                                                                                                
;                                                                                                                                                
                                                                                                                                                 
data want ;                                                                                                                                      
  set have ;                                                                                                                                     
  do _n_ = 1 by 1 until (min_yearmo = max_yearmo) ;                                                                                              
    output ;                                                                                                                                     
    min_yearmo = intnx ("mon", min_yearmo, 1) ;                                                                                                  
  end ;                                                                                                                                          
run ;   

Kind regards

Paul D. 

Sujithpeta
Quartz | Level 8

@hashman 

 

I have created min_yearmo and max_yearmo using below code, both came out with format BEST12.

 

min_yearmo = YEAR(fromdate)*100+month(fromdate);
max_yearmo = YEAR(end_date)*100+month(end_date);

In this scenario, to which format should I change this to apply your code? I tried the format yymmn6. but ended up converting the 2017-11-02 date to 251204. Even still, I ran the code using the above format and the code is taking forever to run so had to stop the code.

 

Appreciate your help. Thanks

hashman
Ammonite | Level 13

@Sujithpeta:

 

In SAS, storing dates as a YYYYMM number is highly deprecated for a variety of reasons. However, if this is what you have in your input data and if you want to keep it such on the way out, some on-the-fly transformation is needed to make them into SAS date values, or otherwise the INTNX function cannot operate properly:

data have ;                                                                                                                                      
  input patientid $ (min_yearmo max_yearmo) (:6.) ;                                                                                              
  cards ;                                                                                                                                        
A  201711  201803                                                                                                                                
B  201801  201803                                                                                                                                
;                                                                                                                                                
                                                                                                                                                 
data want (drop = _:) ;                                                                                                                          
  set have ;                                                                                                                                     
  _minym = input (put (min_yearmo, z6.), yymmn6.) ;                                                                                              
  do _n_ = 1 by 1 until (_minym = input (put (max_yearmo, z6.), yymmn6.)) ;                                                                      
    output ;                                                                                                                                     
    _minym = intnx ("mon", _minym, 1) ;                                                                                                          
    min_yearmo = input (put (_minym, yymmn6.), 6.) ;                                                                                             
  end ;                                                                                                                                          
run ;      

Kind regards

Paul D.

Sujithpeta
Quartz | Level 8
Thanks @hashman
It worked.
Satish_Parida
Lapis Lazuli | Level 10

This not ideal but it works.

data want;
set have;
output;
do while (Min_YearMo<Max_YearMo);
	Min_YearMo_y=floor(Min_YearMo/100);
	Min_YearMo_m=mod(Min_YearMo,100);
	Min_YearMo_m=Min_YearMo_m+1;
	if Min_YearMo_m>12 then do;
		Min_YearMo_m=1;
		Min_YearMo_y=Min_YearMo_y+1;
	end;
	Min_YearMo=Min_YearMo_y*100+Min_YearMo_m;
	if Min_YearMo<Max_YearMo then output;
end;
drop Min_YearMo_y Min_YearMo_m;
run;
Satish_Parida
Lapis Lazuli | Level 10
Please let us know if it worked for you.
yabwon
Onyx | Level 15

Hi @Sujithpeta ,

 

one more approach, when you have numeric values like 201901, could be:

 

data have ;                                                                                                                                      
  input patientid $ min_yearmo max_yearmo ;                                                                                         
  cards ;                                                                                                                                        
A  201711  201803
B  201801  201803
C  201801  201911
;                                                                                                                                                
run;
 
data want ;                                                                                                                                      
  set have ;                                                                                                                                     
  do until (min_yearmo > max_yearmo);
      output ; 
      /*put _all_;*/
      min_yearmo + 1 ;
      if (mod(min_yearmo,100)>12) then min_yearmo + 88; 
  end ;                                                                                                                                          
run ;

 

All the best

Bart

_______________
Polish SAS Users Group: www.polsug.com and communities.sas.com/polsug

"SAS Packages: the way to share" at SGF2020 Proceedings (the latest version), GitHub Repository, and YouTube Video.
Hands-on-Workshop: "Share your code with SAS Packages"
"My First SAS Package: A How-To" at SGF2021 Proceedings

SAS Ballot Ideas: one: SPF in SAS, two, and three
SAS Documentation



Sujithpeta
Quartz | Level 8
@yabwon
Thanks for the solution. Other person code worked for me yesterday. I'll try this approach as well and let you know if it worked. Thanks agian

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
  • 8 replies
  • 1538 views
  • 0 likes
  • 4 in conversation