BookmarkSubscribeRSS Feed
☑ This topic is solved. Need further help from the community? Please sign in and ask a new question.
Eric_Lee
Fluorite | Level 6

barchart_with_lattice.png

Please ignore the gray square in legend, this can be fixed by 'legendItem'.

This is the picture I wanted. The percent of the car produced have been displayed by categories ( the cars' Type and DriveTrain).

 

But, when I generated the figure by statgraph 'barchart_with_no_lattice', the tick values of y axis were not displayed as expected. The code is as follows: 

About the format of 'cateparam.', please refer to the last part.

proc template;
  define statgraph barchart_with_no_lattice;
    begingraph /border=false;

      discreteattrmap name='colors' / ignorecase=true;
        value "Asia"     / lineattrs=(color=&color1.)  fillattrs=(color=&color1.);
        value "Europe"   / lineattrs=(color=&color2.)  fillattrs=(color=&color2.);
        value "USA"      / lineattrs=(color=&color3.)  fillattrs=(color=&color3.);
      enddiscreteattrmap;
      discreteattrvar attrvar=barcolors var=origin attrmap='colors';

      layout overlay /
        yaxisopts = (display=(ticks tickvalues) 
          linearopts=(tickvaluesequence=(start=&xmin. end=&xmax. increment=1) tickvalueformat=cateparam.))
        xaxisopts = (display=(ticks tickvalues)
          linearopts=(viewmax=100 viewmin=0 tickvaluesequence=(start=0 end=100 increment=10)));

        barchart category=paramn response=percent / name='origin' group=barcolors orient=horizontal grouporder=data
          groupdisplay=stack display=(fill);
        discretelegend 'origin';
      endlayout;
    endgraph;
  end;
run;

ods graphics on / reset outputfmt=png imagename='barchart_with_no_lattice';
proc sgrender data=type_new template=barchart_with_no_lattice;
run;

 

The figure generated by 'barchart_with_no_lattice': 

barchart_with_no_lattice.png

Please ignore the gray square in legend, this can be fixed by 'legendItem'.

 

 

And, I used the 'lattice' to display the text for a temporary solution, left and right. In the left figure, I wantted to display the text that should be showed in tick values. Suddendly, I found the TickValueFormat was working as expected, so the width of left figure was set to 0, finally the first figure above was generated. the code I used as follows:

proc template;
  define statgraph barchart_with_lattice;
    begingraph /border=false;

      discreteattrmap name='colors' / ignorecase=true;
        value "Asia"     / lineattrs=(color=&color1.)  fillattrs=(color=&color1.);
        value "Europe"   / lineattrs=(color=&color2.)  fillattrs=(color=&color2.);
        value "USA"      / lineattrs=(color=&color3.)  fillattrs=(color=&color3.);
      enddiscreteattrmap;
      discreteattrvar attrvar=barcolors var=origin attrmap='colors';

      layout lattice / columns=2  columnweights=(0 1.0) rowdatarange=union;

        layout overlay / walldisplay=none yaxisopts=(display=none) xaxisopts=(display=none);
          scatterplot y=paramn x=param /markercharacterposition=right;
        endlayout;

        layout overlay /
          yaxisopts=(display=(ticks tickvalues) 
            linearopts=(tickvaluesequence=(start=&xmin. end=&xmax. increment=1) tickvalueformat=cateparam.))
          xaxisopts=(display=(ticks tickvalues)
            linearopts=(viewmax=100 viewmin=0 tickvaluesequence=(start=0 end=100 increment=10)));

          barchart category=paramn response=percent / name='origin' group=barcolors orient=horizontal grouporder=data
            groupdisplay=stack display=(fill);
          discretelegend 'origin';
        endlayout;

      endlayout;
    endgraph;
  end;
run;

ods graphics on / reset outputfmt=png imagename='barchart_with_lattice';
proc sgrender data=type_new template=barchart_with_lattice;
run;

 

 

Did I miss something in 'barchart_with_no_lattice'? Why did not the TickValueFormat work? 

 

Thanks for any information.

 

The data used by 'PROC SGRENDER' was generated by this code, dataset's name is 'type_new':

data cars;
  set sashelp.cars;
  format _all_;informat _all_;
run;

proc sql noprint;
  create table type01_01 as
    select distinct type,origin,count(distinct model) as count from cars group by type,origin;
  create table type01_02 as
    select distinct type,count(distinct model) as bign from cars group by type;

  create table type01 as
    select lds.*,rds.bign from type01_01 lds left join type01_02 rds on lds.type=rds.type;
quit;

proc sql noprint;
  create table type02_01 as
    select distinct drivetrain,origin,count(distinct model) as count from cars group by drivetrain,origin;
  create table type02_02 as
    select distinct drivetrain,count(distinct model) as bign from cars group by drivetrain;

  create table type02 as
    select lds.*,rds.bign from type02_01 lds left join type02_02 rds on lds.drivetrain=rds.drivetrain;
quit;

data type1;
  length cate param $200 percent 8;
  set type01(in=a) type02(in=b);
  if a then cate='1st Category';
  else cate='2nd Category';
  param=coalescec(type,drivetrain);
  percent=count/bign*100;
run;
proc sort;by cate param;run;

data type9;
  set type1;
  by cate param;
  output;
  if first.cate then do;
    param=strip(cate);call missing(percent,origin);
    output;
  end;
run;
proc sort;by descending cate descending param;run;

data type_new;
  length paramn 8;
  retain paramn;
  set type9;
  by descending cate descending param;
  if _n_=1 then paramn=0;
  if first.param then paramn=paramn+1;
run;

 

The format and macro variables was generated by this code:

data format;
  length fmtname $200 start 8 label type $200;
  set type_new;
  fmtname='cateparam';
  start=paramn;
  label=strip(param);
  type='n';
  keep fmtname start label type;
run;
proc sort data=format nodupkey;by start label;run;

proc format library=work cntlin=format;run;

proc sql noprint;
  select min(start) into:xmin trimmed from format;
  select max(start) into:xmax trimmed from format;
quit;
%put &xmin. &xmax.;

%let color1=vligb;
%let color2=liyg;
%let color3=lioy;

 

The full code also was uploaded by 'txt' in the attachment. 

1 ACCEPTED SOLUTION

Accepted Solutions
DanH_sas
SAS Super FREQ

@ballardw is correct that the bar chart category axis is discrete by default, causing the TickValueFormat in the LINEAROPTS to be ignored. However, bar chart DO support linear category axes. So, if you set the Y axis explicitly to be TYPE=LINEAR, your format should be honored. Let us know if that works for you.

View solution in original post

4 REPLIES 4
ballardw
Super User

I don't think the base of bar charts can be considered "linear" as they are categorical. So I'm not surprised that LINEAROPTS applied to that axis misbehave. Kind of says so right in the syntax:

barchart category=<variable name>

The variable is categorical.

 


@Eric_Lee wrote:

barchart_with_lattice.png

Please ignore the gray square in legend, this can be fixed by 'legendItem'.

This is the picture I wanted. The percent of the car produced have been displayed by categories ( the cars' Type and DriveTrain).

 

But, when I generated the figure by statgraph 'barchart_with_no_lattice', the tick values of y axis were not displayed as expected. The code is as follows: 

About the format of 'cateparam.', please refer to the last part.

proc template;
  define statgraph barchart_with_no_lattice;
    begingraph /border=false;

      discreteattrmap name='colors' / ignorecase=true;
        value "Asia"     / lineattrs=(color=&color1.)  fillattrs=(color=&color1.);
        value "Europe"   / lineattrs=(color=&color2.)  fillattrs=(color=&color2.);
        value "USA"      / lineattrs=(color=&color3.)  fillattrs=(color=&color3.);
      enddiscreteattrmap;
      discreteattrvar attrvar=barcolors var=origin attrmap='colors';

      layout overlay /
        yaxisopts = (display=(ticks tickvalues) 
          linearopts=(tickvaluesequence=(start=&xmin. end=&xmax. increment=1) tickvalueformat=cateparam.))
        xaxisopts = (display=(ticks tickvalues)
          linearopts=(viewmax=100 viewmin=0 tickvaluesequence=(start=0 end=100 increment=10)));

        barchart category=paramn response=percent / name='origin' group=barcolors orient=horizontal grouporder=data
          groupdisplay=stack display=(fill);
        discretelegend 'origin';
      endlayout;
    endgraph;
  end;
run;

ods graphics on / reset outputfmt=png imagename='barchart_with_no_lattice';
proc sgrender data=type_new template=barchart_with_no_lattice;
run;

 

The figure generated by 'barchart_with_no_lattice': 

barchart_with_no_lattice.png

Please ignore the gray square in legend, this can be fixed by 'legendItem'.

 

 

And, I used the 'lattice' to display the text for a temporary solution, left and right. In the left figure, I wantted to display the text that should be showed in tick values. Suddendly, I found the TickValueFormat was working as expected, so the width of left figure was set to 0, finally the first figure above was generated. the code I used as follows:

proc template;
  define statgraph barchart_with_lattice;
    begingraph /border=false;

      discreteattrmap name='colors' / ignorecase=true;
        value "Asia"     / lineattrs=(color=&color1.)  fillattrs=(color=&color1.);
        value "Europe"   / lineattrs=(color=&color2.)  fillattrs=(color=&color2.);
        value "USA"      / lineattrs=(color=&color3.)  fillattrs=(color=&color3.);
      enddiscreteattrmap;
      discreteattrvar attrvar=barcolors var=origin attrmap='colors';

      layout lattice / columns=2  columnweights=(0 1.0) rowdatarange=union;

        layout overlay / walldisplay=none yaxisopts=(display=none) xaxisopts=(display=none);
          scatterplot y=paramn x=param /markercharacterposition=right;
        endlayout;

        layout overlay /
          yaxisopts=(display=(ticks tickvalues) 
            linearopts=(tickvaluesequence=(start=&xmin. end=&xmax. increment=1) tickvalueformat=cateparam.))
          xaxisopts=(display=(ticks tickvalues)
            linearopts=(viewmax=100 viewmin=0 tickvaluesequence=(start=0 end=100 increment=10)));

          barchart category=paramn response=percent / name='origin' group=barcolors orient=horizontal grouporder=data
            groupdisplay=stack display=(fill);
          discretelegend 'origin';
        endlayout;

      endlayout;
    endgraph;
  end;
run;

ods graphics on / reset outputfmt=png imagename='barchart_with_lattice';
proc sgrender data=type_new template=barchart_with_lattice;
run;

 

 

Did I miss something in 'barchart_with_no_lattice'? Why did not the TickValueFormat work? 

 

Thanks for any information.

 

The data used by 'PROC SGRENDER' was generated by this code, dataset's name is 'type_new':

data cars;
  set sashelp.cars;
  format _all_;informat _all_;
run;

proc sql noprint;
  create table type01_01 as
    select distinct type,origin,count(distinct model) as count from cars group by type,origin;
  create table type01_02 as
    select distinct type,count(distinct model) as bign from cars group by type;

  create table type01 as
    select lds.*,rds.bign from type01_01 lds left join type01_02 rds on lds.type=rds.type;
quit;

proc sql noprint;
  create table type02_01 as
    select distinct drivetrain,origin,count(distinct model) as count from cars group by drivetrain,origin;
  create table type02_02 as
    select distinct drivetrain,count(distinct model) as bign from cars group by drivetrain;

  create table type02 as
    select lds.*,rds.bign from type02_01 lds left join type02_02 rds on lds.drivetrain=rds.drivetrain;
quit;

data type1;
  length cate param $200 percent 8;
  set type01(in=a) type02(in=b);
  if a then cate='1st Category';
  else cate='2nd Category';
  param=coalescec(type,drivetrain);
  percent=count/bign*100;
run;
proc sort;by cate param;run;

data type9;
  set type1;
  by cate param;
  output;
  if first.cate then do;
    param=strip(cate);call missing(percent,origin);
    output;
  end;
run;
proc sort;by descending cate descending param;run;

data type_new;
  length paramn 8;
  retain paramn;
  set type9;
  by descending cate descending param;
  if _n_=1 then paramn=0;
  if first.param then paramn=paramn+1;
run;

 

The format and macro variables was generated by this code:

data format;
  length fmtname $200 start 8 label type $200;
  set type_new;
  fmtname='cateparam';
  start=paramn;
  label=strip(param);
  type='n';
  keep fmtname start label type;
run;
proc sort data=format nodupkey;by start label;run;

proc format library=work cntlin=format;run;

proc sql noprint;
  select min(start) into:xmin trimmed from format;
  select max(start) into:xmax trimmed from format;
quit;
%put &xmin. &xmax.;

%let color1=vligb;
%let color2=liyg;
%let color3=lioy;

 

The full code also was uploaded by 'txt' in the attachment. 


 

Eric_Lee
Fluorite | Level 6
Thanks for your reply. This make it sense about 'category'.
DanH_sas
SAS Super FREQ

@ballardw is correct that the bar chart category axis is discrete by default, causing the TickValueFormat in the LINEAROPTS to be ignored. However, bar chart DO support linear category axes. So, if you set the Y axis explicitly to be TYPE=LINEAR, your format should be honored. Let us know if that works for you.

Eric_Lee
Fluorite | Level 6
It works as expected. Thank you very much. Also, I got the idea about the usage of 'category'. Lots of help.

hackathon24-white-horiz.png

The 2025 SAS Hackathon Kicks Off on June 11!

Watch the live Hackathon Kickoff to get all the essential information about the SAS Hackathon—including how to join, how to participate, and expert tips for success.

YouTube LinkedIn

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
  • 4 replies
  • 1459 views
  • 4 likes
  • 3 in conversation