6

In R you can perform a condition across all rows in a column variable by using the all() or any() function. Is there an equivalent method in SAS?

I want condition if ANY rows in column x are negative, this should return TRUE.

Or, if ALL rows in column y are negative, this should return TRUE.

For example

x   y
-1  -2
2   -4
3   -4
4   -3

In R:

  • all(x<0) would give the output FALSE
  • all(y<0) would give the output TRUE

I wish to replicate the same column-wise operation in SAS.

Joe
  • 62,789
  • 6
  • 49
  • 67
MWw
  • 150
  • 1
  • 8
  • 1
    By default SAS operates on a single row at a time and loops so this behaviour is built in. It's not clear what you're looking for as output however, so we can't answer your question at this point in time. – Reeza Mar 20 '18 at 01:17
  • 1
    Please show your desired output. – Quentin Mar 20 '18 at 01:22
  • 2
    @Reeza - You can do `all(column < 0)` in R. Because SAS only knows about a row at a time, you can't do such column-wise operations. You can look row-wise in SAS easily, but I think the question is the opposite of that. – thelatemail Mar 20 '18 at 01:34
  • @Reeza Yes, thelatemail is correct my question is posed at doing column-wise operations. The result I wish to achieve is a output from SAS that says if the entire column of x or y is composed of negative values. – MWw Mar 20 '18 at 01:46
  • 2
    Probably doable through `sql`: `proc sql; select sum(x >= 0)=0 from table; quit;` (untested) – thelatemail Mar 20 '18 at 02:16
  • 2
    This is most likely an X-Y question. SAS is not a matrix language, and does not have functions like you describe; but it has very different ways of doing things than matrix languages. What are you doing, in a larger picture, such that `any()` or `all()` is something you'd want to use? – Joe Mar 20 '18 at 06:08
  • Perhaps someone can post an IML solution? – Quentin Mar 20 '18 at 12:22
  • If @MWw would like to see an IML solution I'd certainly be happy to. – Joe Mar 20 '18 at 16:29
  • IML answer provided; if it's of interest, please add [tag:sas-iml] to the tags. [tag:r] removed as this is not an R question. – Joe Mar 20 '18 at 22:32

3 Answers3

8

For completeness' sake, here is the SAS-IML solution. Of course, it's trivial as the any and all functions exist by the same name... I also include an example of using loc to identify the positive elements.

data have ;
  input x y @@;
cards;
1 2 
2 4 
3 -4 
4 -3 
;
run;

proc iml;
    use have;
    read all var {"x" "y"};
    print x y;
    x_all = all(x>0);
    x_any = any(x>0);
    y_all = all(y>0);
    y_any = any(y>0);
    y_pos = y[loc(y>0)];

    print x_all x_any y_all y_any;
    print y_pos;
quit;
Joe
  • 62,789
  • 6
  • 49
  • 67
7

If you want to operate on all observations that might be easiest to do using SQL summary functions.

SAS will evaluate boolean expressions as 1 for true and 0 for false. So to find out if any observation has a condition you want to test if the MAX( condition ) is true (ie equal to 1). To find out if all observations have the condition you want to test if the MIN( condition ) is true.

data have ;
  input x y @@;
cards;
-1 -2 2 -4 3 -4 4 -3 
;

proc sql ;
create table want as 
  select 
     min(x<0) as ALL_X
   , max(x<0) as ANY_X
   , min(y<0) as ALL_Y
   , max(y<0) as ANY_Y
  from have
;
quit;

Result

Obs    ALL_X    ANY_X    ALL_Y    ANY_Y
 1       0        1        1        1

Tom
  • 47,574
  • 2
  • 16
  • 29
7

SQL is probably the most feels-like similar way to do this, but the data step is just as efficient, and lends itself a bit better to any sort of modification - and frankly, if you're trying to learn SAS, is probably the way to go simply from the point of view of learning how to do things the SAS way.

data want;
  set have end=eof;
  retain any_x all_x;         *persist the value across rows;
  any_x = max(any_x, (x>0));  *(x>0) 1=true 0=false, keep the MAX (so keep any true);
  all_x = min(all_x, (x>0));  *(x>0) keep the MIN (so keep any false);
  if eof then output;         *only output the final row to a dataset;
  *and/or;
  if eof then do;             *here we output the any/all values to macro variables;
    call symputx('any_x',any_x); *these macro variables can further drive logic;
    call symputx('all_x',all_x); *and exist in a global scope (unless we define otherwise);
  end;
run;
Joe
  • 62,789
  • 6
  • 49
  • 67