0

I am looking to have a flexible importing structure into my SAS code. The import table from excel looks like this:

data have;
input Fixed_or_Floating $ asset_or_liability $ Base_rate_new;
datalines;

FIX A 10
FIX L Average Maturity
FLT A 20
FLT L Average Maturity
;
run;

The original dataset I'm working with looks like this:

data have2;
input ID Fixed_or_Floating $ asset_or_liability $ Base_rate;
datalines;

1 FIX A 10
2 FIX L 20
3 FIX A 30
4 FLT A 40
5 FLT L 30
6 FLT A 20
7 FIX L 10
;
run;

The placeholder "Average Maturity" exists in the excel file only when the new interest rate is determined by the average maturity of the bond. I have a separate function for this which allows me to search for and then left join the new base rate depending on the closest interest rate. An example of this is such that if the maturity of the bond is in 10 years, i'll use a 10 year interest rate.

So my question is, how can I perform a simple merge, using similar code to this:

proc sort data = have;
by fixed_or_floating asset_or_liability;
run;

proc sort data = have2;
by fixed_or_floating asset_or_liability;
run;

data have3 (drop = base_rate);
merge have2 (in = a)
      have1 (in = b);
by fixed_or_floating asset_or_liability;

run;

The problem at the moment is that my placeholder value doesn't read in and I need it to be a word as this is how the excel works in its lookup table - then I use an if statement such as

if base_rate_new = "Average Maturity" then do;

(Insert existing Function Here)

end;

so just the importing of the excel with a placeholder function please and thank you.

TIA.

78282219
  • 593
  • 5
  • 21

1 Answers1

0

I'm not 100% sure if this behaviour corresponds with how your data appears once you import it from excel but if I run your code to create have I get:

NOTE: Invalid data for Base_rate_new in line 145 7-13.
RULE:      ----+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+--
145        FIX L Average Maturity
Fixed_or_Floating=FIX asset_or_liability=L Base_rate_new=. _ERROR_=1 _N_=2
NOTE: Invalid data for Base_rate_new in line 147 7-13.
147        FLT L Average Maturity
Fixed_or_Floating=FLT asset_or_liability=L Base_rate_new=. _ERROR_=1 _N_=4
NOTE: SAS went to a new line when INPUT statement reached past the end of a line.
NOTE: The data set WORK.HAVE has 4 observations and 3 variables.

Basically it's saying that when you tried to import the character strings as numeric it couldn't do it so it left them as null values. If we print the table we can see the null values:

proc print data=have;
run;

Result:

Fixed_or_    asset_or_      Base_
Floating     liability    rate_new

   FIX           A           10
   FIX           L            .
   FLT           A           20
   FLT           L            .

Assuming this truly is what your data looks like then we can use the coalesce function to achieve your goal.

data have3 (drop = base_rate);
  merge have2 (in = a)
        have (in = b);
  by fixed_or_floating asset_or_liability;
  base_rate_new = coalesce(base_rate_new,base_rate);
run;

The result of doing this gives us this table:

       Fixed_or_    asset_or_      Base_
 ID    Floating     liability    rate_new

  1       FIX           A           10
  3       FIX           A           10
  2       FIX           L           20
  7       FIX           L           20
  4       FLT           A           20
  6       FLT           A           20
  5       FLT           L           30

The coalesce function basically returns the first non-null value it can find in the parameters you pass to it. So when base_rate_new already has a value it uses that, and if it doesn't it uses the base_rate field instead.

Robert Penridge
  • 8,424
  • 2
  • 34
  • 55
  • Hi, I appreciate your answer, it is very reasonable! Unfortunately, I'm looking for a way to make a placeholder / character such that It can be used in the next function as an indicator to be filled by my next programme. I think the best way to go about this is to leave it blank and then do if base_rate_new = . then do; (Insert my next programme here) end; – 78282219 Apr 26 '18 at 19:28
  • 1
    No problem. Just be aware that you can't have a column contain both numeric and character values. You could possibly apply a custom format to the numeric column and then check the result of the custom format in your next program though which would kind of achieve what you want (I think). – Robert Penridge Apr 26 '18 at 19:35
  • 1
    @78282219 Alternatively have your new program just do the check: `if base_rate_new eq . then do;` which would work just as well and work on a numeric column. – Robert Penridge Apr 26 '18 at 19:36
  • You were correct with your numeric and char so I've decided to go for -999 as a placeholder – 78282219 Apr 30 '18 at 11:00