BookmarkSubscribeRSS Feed
Ronein
Meteorite | Level 14

Hello

I am trying to merge two tables and the task is to spread out the value of the grand_total.

What is the best way to do it?

I know that I can add help field in each of tables (with value 1 for example) and then to merge them.

But I think there is a more clever way to do it.

 

Any advice?

 /************************************************************************/
  *--------------------------------------------------------------------*
          |Calculate PCT that each group contributes |
  *--------------------------------------------------------------------*
/************************************************************************/;

data RawData1;
input  region $  ID $  amount;
cards;
North 1 10
North 2 20
North 3 30
North 4 40
North 5 100
South 6 60
South 7 70
South 8 80
South 9 90
East 10 100
East 11 200
;
run;
proc means data=RawData1 noprint nway;
var amount;
class region;
output out=output1(keep=RegionTotal region)
               sum(amount)=RegionTotal;
Run;
proc means data=RawData1 noprint ;
var amount;
output out=output2(keep=Grand_Total)
               sum(amount)=Grand_Total;
Run;
Data output3;
Merge output1(in=a) output2(in=b);
pct=(RegionTotal/Grand_Total);
Format pct percent6.2  RegionTotal  Grand_Total dollar10.;
Run;
7 REPLIES 7
Ronein
Meteorite | Level 14

I know to to do it by adding help variable.

Is there a shorter way ?

data RawData1;
input  region $  ID $  amount;
cards;
North 1 10
North 2 20
North 3 30
North 4 40
North 5 100
South 6 60
South 7 70
South 8 80
South 9 90
East 10 100
East 11 200
;
run;


proc means data=RawData1 noprint nway;
var amount;
class region;
output out=output1(keep=RegionTotal region)
               sum(amount)=RegionTotal;
Run;


proc means data=RawData1 noprint ;
var amount;
output out=output2(keep=Grand_Total)
               sum(amount)=Grand_Total;
Run;


Data output1;
set output1;
help=1;
Run;


Data output2;
set output2;
help=1;
Run;


Data output3;
Merge output1(in=a) output2(in=b);
by help;
pct=(RegionTotal/Grand_Total);
Format pct percent6.2  RegionTotal  Grand_Total dollar10.;
Run;
proc print data=output3 noobs;run;

 

ChrisNZ
Tourmaline | Level 20

Like this? 

proc summary data=RawData1 ;
  var amount;
  class region;
  output out=SUM sum=;
run; 

data output3;
  merge SUM(where=(_TYPE_=0) rename=(AMOUNT=GrandTotal )) 
        SUM(where=(_TYPE_=1) rename=(AMOUNT=RegionTotal));
  PCT=(RegionTotal/GrandTotal);
  format PCT percent6.2  RegionTotal  GrandTotal dollar10.;
run;

 

Ronein
Meteorite | Level 14

Thanks.

If you run the code you can see that column "PCT"  has null  values (only value in first row is not null).

So actually we have not received the requested results.

Kurt_Bremser
Super User

There's no need for the merge:

data RawData1;
input  region $  ID $  amount;
cards;
North 1 10
North 2 20
North 3 30
North 4 40
North 5 100
South 6 60
South 7 70
South 8 80
South 9 90
East 10 100
East 11 200
;
run;

proc means data=RawData1 noprint nway;
var amount;
class region;
output
  out=output1 (keep=RegionTotal region)
  sum(amount)=RegionTotal
;
run;

proc sql noprint;
select sum(regiontotal) into :grandtotal
from output1;
quit;

data output3;
set output1;
grand_total = &grandtotal;
pct = (RegionTotal/Grand_Total);
format
  pct percent6.2
  RegionTotal Grand_Total dollar10.
;
run;

proc print data=output3 noobs;
run;

Result:

              Region        grand_
region         Total         total       pct

East            $300          $800      38% 
North           $200          $800      25% 
South           $300          $800      38% 
Kurt_Bremser
Super User

And the whole thing can be made even shorter:

data RawData1;
input region $ ID $ amount;
cards;
North 1 10
North 2 20
North 3 30
North 4 40
North 5 100
South 6 60
South 7 70
South 8 80
South 9 90
East 10 100
East 11 200
;
run;

proc sql noprint;
select sum(regiontotal) into :grandtotal
from output1;
quit;

data output;
set rawdata1;
by region notsorted;
retain region_total;
grand_total = &grandtotal;
format
  region_total grand_total dollar10.
  pct percent6.2
;
if first.region
then region_total = amount;
else region_total + amount;
if last.region
then do;
  pct = region_total / grand_total;
  output;
end;
keep region region_total grand_total pct;
run;

proc print data=output noobs;
run;

Result:

             region_        grand_
region         total         total       pct

North           $200          $800      25% 
South           $300          $800      38% 
East            $300          $800      38% 
ChrisNZ
Tourmaline | Level 20

Of course you are right. Sorry I typed this with access to SAS (and without my brain plugged).

This should work (hopefully mybrain is more awake now, still untested):

 

data output3;
  merge SUM(where=(_TYPE_=0) ) 
        SUM(where=(_TYPE_=1) rename=(AMOUNT=RegionTotal));
if _N_ =1 then GrandTotal=Amount;
retain GrandTotal;
PCT=(RegionTotal/GrandTotal); format PCT percent6.2 RegionTotal GrandTotal dollar10.; run;

 

Kurt_Bremser
Super User

And the simplest solution is a SQL with a sub-select:

proc sql;
create table want as
select
  a.region,
  sum(a.amount) as region_total format=dollar10.,
  (select sum(b.amount) from rawdata1 b) as grand_total format=dollar10.,
  calculated region_total / calculated grand_total as pct format=percent6.2
from rawdata1 a
group by a.region;
quit;

SAS Innovate 2025: Save the Date

 SAS Innovate 2025 is scheduled for May 6-9 in Orlando, FL. Sign up to be first to learn about the agenda and registration!

Save the date!

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
  • 7 replies
  • 1285 views
  • 0 likes
  • 3 in conversation