BookmarkSubscribeRSS Feed
NewUsrStat
Lapis Lazuli | Level 10

Hi guys, 

 

suppose to have the following dataset: 

 

data DB;
  input ID :$20. Flag :$20. Observation;
cards;
0001  Y  .
0001  N  1
0001  N  .
0001  N  1
0002  N  1
0002  N  1
0002  N  1
0002  N  .

...;

Is there a way to sum all "Observation(s)" =1 but only for IDs having at least one Flag = "Y"?

Desired output: sum = 1

Thank you in advance

8 REPLIES 8
Quentin
Super User

Can you please show the output you want?

 

If you want the same dataset, with a sum added, you could use a double-DOW loop, e.g.

 

data want ;
   do until(last.id) ;
     set db ;
     by id ;
     if flag='Y' then _flagged=1 ;
     _sum=sum(observation,_sum,0) ;
   end ;
   if _flagged then mysum=_sum ;
   do until(last.id) ;
     set db ;
     by id ;
     output ;
  end ;
run ;

 

The Boston Area SAS Users Group is hosting free webinars!

Register now at https://www.basug.org/events.
NewUsrStat
Lapis Lazuli | Level 10
Thank you very much for your help. I just need the sum stored in an output db since the sum should refer to all IDs with at least one value of "Flag = Y" and not in particular to one or another ID.
Tom
Super User Tom
Super User

This is something that SQL syntax would make it easy to express.

 

You describe it as a SUM but to me it looks more like a COUNT.

create table want as 
select count(distinct id) as n_ids_flagged 
  from have 
  where observation=1
    and id in (select id from have where flag='Y')
;

 

Quentin
Super User

From your example data, shouldn't the answer be 2 rather than 1?

 

You could still use a DOW-loop approach to flag the IDs of interest, then do the summing of the flagged records:

 

data want (keep=mysum);
   do until(last.id) ;
     set db ;
     by id ;
     if flag='Y' then _flagged=1 ;
   end ;
   do until(last.id) ;
     set db end=last ;
     by id ;
     if _flagged then mysum++observation;
  end ;
  if last then output ;
run ;

Or via SQL:

proc sql ;
  create table want as 
  select sum(observation) as mysum
  from
    (select id, observation
      from db
      group by id
      having max(flag)='Y'
    )
 ;
quit ;

 

The Boston Area SAS Users Group is hosting free webinars!

Register now at https://www.basug.org/events.
yabwon
Amethyst | Level 16

I think it can be done with one data pass:

data DB;
  input ID :$20. Flag :$20. Observation;
cards;
0001  Y  .
0001  N  1
0001  N  .
0001  N  1
0002  N  1
0002  N  1
0002  N  1
0002  N  .
0003  N  .
0003  N  1
0003  Y  .
0003  N  1
;
run;

data want;
  set db end=_E_;
  by id;
  if first.id then do; s=0; check=0; end;
  s + (Observation=1);
  check + (Flag="Y");
  if last.id and check then sum+s;
  if _E_;
run;
proc print data=want;
run;

B.

_______________
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



yabwon
Amethyst | Level 16

I think even almost "unconditionall" 😄

data want2;
  set db end=_E_;
  by id;
  
  s=s*(^first.id); 
  check=check*(^first.id);

  s + (Observation=1);
  check + (Flag="Y");
  sum+s*(last.id*check);

  if _E_;
run;
proc print data=want2;
run;

B

_______________
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



Quentin
Super User

I like it,  Bart 😁

 

Since OP hints that there could be more than one record for an ID with flag='Y', perhaps:


check + (Flag="Y");

 


Should be:

check + ((Flag="Y") and (Not check));

?

The Boston Area SAS Users Group is hosting free webinars!

Register now at https://www.basug.org/events.
yabwon
Amethyst | Level 16

in this case we can do it like @hashman :

 

^^check

or 

check&1

{EDIT:} or even just

& check

 

 

data want2;
  set db end=_E_;
  by id;
  
  s=s*(^first.id); 
  check=check*(^first.id);

  s + (Observation=1);
  check + (Flag="Y");
  sum+s*(last.id*^^check);
  /* sum+s*(last.id*check&1); */
  /* sum+s*(last.id & check); */

  if _E_;
run;
proc print data=want2;
run;

 

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



Catch up on SAS Innovate 2026

Nearly 200 sessions are now available on demand with the SAS Innovate Digital Pass.

Explore Now →
Mastering the WHERE Clause in PROC SQL

SAS' Charu Shankar shares her PROC SQL expertise by showing you how to master the WHERE clause using real winter weather data.

Find more tutorials on the SAS Users YouTube channel.

Discussion stats
  • 8 replies
  • 182 views
  • 4 likes
  • 4 in conversation