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

So I have the following code:

 

%let n_periods=5;

data table1;
	input start : MMDDYY10.  end : MMDDYY10. c_date : MMDDYY10.;
	format start end c_date MMDDYY10.;
	datalines;
1/1/2016 12/31/2016 12/31/2016
7/1/2016 6/30/2017 12/31/2016
7/1/2015 6/30/2016 12/31/2016
7/1/2015 6/30/2018 12/31/2016
7/1/2013 6/30/2023 12/31/2016
9/1/2010 10/31/2020 12/31/2016
7/1/2017 6/30/2018 12/31/2016
3/1/2008 2/28/2009 12/31/2016
1/1/2013 12/31/2013 12/31/2016
9/1/2011 10/31/2012 12/31/2016
;
run;

data periods (drop=_i);
  set table1;
  array per[&n_periods.];
  do _i = 1 to &n_periods.;
    per[_i] = c_date-365*_i;
  end;
run;

proc iml;
	start factor_dev(start_dt,end_dt,c_date);
    	accrued=c_date-start_dt;
    	duration=end_dt-start_dt;
			if accrued/duration>1 then do ;
				factor_dev=1;
			end;
			else if accrued/duration<0 then do;
				factor_dev=0;
			end;
			else if accrued/duration then do;
				factor_dev=accrued/duration;
			end;
			return (factor_dev);
	finish;	
		periods=j(10,3,0);
		use periods;
		read all var _all_ into periods;
		close periods;
		factor_dev_acu=j(dimension(periods)[1,1],&n_periods.,0);
		 print periods;
	do i=1 to dimension(periods)[1,1];
		do j=1 to &n_periods.;
			factor_dev_acu[i,j]=factor_dev(periods[i,1],periods[i,2],periods[i,j+2]);
		end;
	end;
print factor_dev_acu;

When I run it, I get the "ERROR: (execution) Matrix has not been set to a value." error. 

 

The problem appears to be in line 64. I can't find the reason why it's not accepting the third parameter, if I change it to 

periods[i,3]

The program executes without errors, but I can't seem to be able to use anything other than number constants.

Any idea on what I'm doing wrong?

1 ACCEPTED SOLUTION

Accepted Solutions
PaigeMiller
Diamond | Level 26

Logic error here:

else if accrued/duration then do;

This executes if accrued/duration is exactly equal to one, otherwise no value is returned, hence the error you are seeing.

 

The proper code is

else do;

 

 

--
Paige Miller

View solution in original post

5 REPLIES 5
PaigeMiller
Diamond | Level 26

Logic error here:

else if accrued/duration then do;

This executes if accrued/duration is exactly equal to one, otherwise no value is returned, hence the error you are seeing.

 

The proper code is

else do;

 

 

--
Paige Miller
Rick_SAS
SAS Super FREQ

In your IF-THEN/ELSE statements., you have handled the cases where ACCRUED is nonzero, but the error is occuring when ACCRUED=0. Define a result for that situation.

 

...
else if accrued/duration then do;  /* handles all nonzero in (0,1) */  				 
  factor_dev=accrued/duration;
end;
else 
   factor_dev = THE_RESULT_WHEN_accrued_IS_ZERO;
PaigeMiller
Diamond | Level 26

@Rick_SAS wrote:

In your IF-THEN/ELSE statements., you have handled the cases where ACCRUED is nonzero, but the error is occuring when ACCRUED=0. Define a result for that situation.

 

...
else if accrued/duration then do;  /* handles all nonzero in (0,1) */  				 
  factor_dev=accrued/duration;
end;
else 
   factor_dev = THE_RESULT_WHEN_accrued_IS_ZERO;

I don't see a reason to use "if accrued/duration" in this IF/THEN logic flow. It just complicates things. A simple "else do;" will work here, because cases where the ratio is <0 and the ratio is >1 are previously covered.

--
Paige Miller
Rick_SAS
SAS Super FREQ

Hi Paige. No, that logic is not correct. The  OP's last ELSE IF statement evaluates to TRUE whenever the condition is nonzero, but none of the cases cover the situation when the expression is exactly zero. 

 

You don't need to use IML to see this. IF-THEN/ELSE statements are the same throughout SAS, including the DATA step:

 

data Want;
input accrdur @@;
if accrdur>1 then do ;
	factor_dev=1;
end;
else if accrdur<0 then do;
	factor_dev=2;
end;
else if accrdur then do;  /* TRUE when nonzero */
	factor_dev=3;
end;
else                               /* handle zero */
   factor_dev=4;
datalines;
2 -2 0.5 0
;

proc print; run;
Datino
Obsidian | Level 7

So, if I add an else-do, the case where the expression evaluates to zero are covered.

 

Seems to me both of you are right Smiley Happy, and I get a bad mark for faulty logic Smiley Indifferent

sas-innovate-white.png

Special offer for SAS Communities members

Save $250 on SAS Innovate and get a free advance copy of the new SAS For Dummies book! Use the code "SASforDummies" to register. Don't miss out, May 6-9, in Orlando, Florida.

 

View the full agenda.

Register now!

From The DO Loop
Want more? Visit our blog for more articles like these.
Discussion stats
  • 5 replies
  • 2981 views
  • 1 like
  • 3 in conversation