BookmarkSubscribeRSS Feed
vThanu
Calcite | Level 5

data have;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 3 5
;

 

I want to find out the last non-missing value?

Generally if we use coalesce function we get first non-missing value right.

I am looking for last non-missing value.... in the same sequencial order (a,b.c.d...) or (A--D);

 

Thanks in advance

9 REPLIES 9
DanielLangley
Quartz | Level 8
data have;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 3 5
;
run;

data want(drop = i);
set have;
array nums[*] A--D;
do i = dim(nums) to 1 by -1 until (i=1 or vvalue(nums[i]) ne . );
	LastNonMissing = nums[i];
end;
run;

LastNonMissing will be missing if the entire row is missing.

RW9
Diamond | Level 26 RW9
Diamond | Level 26

As an alternative to the array method:

data have;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 3 5
;
run;

data want;
  set have;
  lastmissing=scan(catx(',',of a--d),-1,',');
run;
mansour_ib_sas
Pyrite | Level 9
data want;
set have;
NM= coalesce(d,c,b,a);
run;
RW9
Diamond | Level 26 RW9
Diamond | Level 26

Yes, the coalesce is a good idea, only problem is you can't do lists in reverse.  It would be great to do:

  lastmissing=coalesce(of d--a);

But we can't as that's not the order of the variables.  So needing to put a lot of variables in the line could get long winded.  

 

DanielLangley
Quartz | Level 8

Hi @RW9 This is a really elegant solution however sometimes numbers contain commas which could throw your results off.

 

 

data have;
format a b c d comma9.;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 3 5
4 . 3000 .
;
run;

data want(drop = i);
set have;
array nums[*] A--D;
do i = dim(nums) to 1 by -1 until (i=1 or nums[i] ne . ); *Modified to get rid of vvalue;
	LastNonMissing = nums[i];
end;
lastmissing=scan(catx(',',of a--d),-1,','); *from RW9;
NM= coalesce(d,c,b,a); * from mansour_ib_sas;
run;

 

 

RW9
Diamond | Level 26 RW9
Diamond | Level 26

True (although whether actual numbers (rather than formatted) can contain commas is a different discussion Smiley Happy ) and hadn't though about that.  Just replace the comma usage:

data want;
  set have;
  lastmissing=scan(catx('|',of a--d),-1,'|');
run;

A bar (pipe) for instance.

novinosrin
Tourmaline | Level 20

Hi @vThanu 

 

Thank you for the interesting question. 

 

The solutions you received so far:

 

1. Loop aka linear search

2. Colaesce ( problem: what if you have numerous variables to reverse the list, this would involve loading the list in a macro var in a reverse order

3. scan ( didn;t work as it didn;t produce 4 6 5 5 as the wanted result but I think this is a slick approach regardless)

 

One easy approach in my opinion is

 

data have;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 3 5
;
run;

data want;
set have;
temp=compress(cats(of a--d),'.');
lastnonmissing=char(temp,length(temp));
drop temp;
run;

This handles the variable list conveniently, stripping of '.' from the last and extracting the last one.

 

Results:

 

a b c d lastnonmissing 
1 2 . 4 4 
4 . 3 6 6 
2 3 5 . 5 
. 2 3 5 5 

 

mansour_ib_sas
Pyrite | Level 9

Another solution is possible:

data test;
input a b c d;
cards;
1 2 . 4
4 . 3 6
2 3 5 .
. 2 . .
;
run;

proc contents noprint  data=test out=test1;run;

proc sql noprint ;
select name into : col separated by ' ' from test1 order by varnum desc;
quit;

 
data test1(drop=i);
set test;
array nums &col.;
do i=dim(nums) to 1 by -1;
if nums(i) ^= . then do;
 lnm=nums(i);
output;
leave;
end;
end;
run;

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
  • 9 replies
  • 4756 views
  • 1 like
  • 5 in conversation