Transparent line in a line plot? - sas

Hello intelligent people.
Can anyone tell me how to get a graph/line in a line plot transparent in SAS EG or in a SAS PROC GPLOT procedure? (2 lines are on top of eachother, so cannot see the underlying line).

Just add the option transparency
ods graphics on / width=66%;
data test;
do x = 1 to 10 by .1;
up = 11 - x;
down = 9 - x;
y = x*x/10;
output;
end;
proc sgplot data=test;
series x=x y=y / lineattrs=(color=orange thickness=3);
band x=x upper=up lower=down / transparency=.3;
run;

Related

SAS - SGPLOT - adding XAXIS group label

I am looking for an option to add a group label (grouping value of Xaxis). I tried X2AXIS and REFLINE option but none is working exactly. (see attached image for reference - I would like to add G1, G2 and G3 with brackets)
As a starting point, consider
data have;
call streaminit(2021);
do x = 1 to 6;
do _n_ = 1 to 2+ rand('integer', 5);
y = 5 + rand('integer', 10);
group = cats ('G', int((x+1)/2));
output;
end;
end;
run;
ods html file='plot.html';
proc sgplot data=have;
vbox y / group=group category=x;
run;
ods html close;
which produces

SAS SGPLOT VBOX: Display Mean and Median on Boxplot

I am trying to make a boxplot by using the SGPLOT in SAS. I would like to use SGPLOT with VBOX statement to flag out the Mean and Median on the gragh for each box.
Below is the data set I created as an example. Can someone give me a kind help on that?
/* Set the graphics environment */
goptions reset=all cback=white border htitle=12pt htext=10pt;
/* Create a sample data set to plot */
data one(drop=i);
do i=1 to 10;
do xvar=1 to 9 by 2;
yvar=ranuni(0)*100;
output;
end;
end;
run;
/* Sort the data by XVAR */
proc sort data=one;
by xvar;
run;
/* Use the UNIVARIATE procedure to determine */
/* the mean and median values */
proc univariate data=one noprint;
var yvar;
by xvar;
output mean=mean median=median out=stat;
run;
/* Merge the mean and median values back */
/* into the original data set by XVAR */
data all;
merge one stat;
by xvar;
run;
Use VBOX for box plot, SCATTER for mean/median.
/*--Compute the Mean and Median by sex--*/
proc means data=sashelp.heart;
class deathcause;
var cholesterol;
output out=heart(where=(_type_ > 0) keep=deathcause mean median _type_)
mean = mean
median = median;
run;
/*--Merge the data--*/
data heart2;
keep deathcause mean median cholesterol;
set sashelp.heart heart;
run;
proc print data=heart2;run;
/*--Box plot with connect and group colors--*/
ods graphics / reset ANTIALIASMAX=5300 width=5in height=3in imagename='Box_Group_Multi_Connect';
title 'Cholesterol by Cause of Death';
proc sgplot data=heart2 noautolegend noborder;
vbox cholesterol / category=deathcause group=deathcause;
scatter x=deathcause y=mean / name='mean' legendlabel='Mean' markerattrs=(color=green);
scatter x=deathcause y=median / name='median' legendlabel='Median' markerattrs=(color=red);
keylegend "mean" "median" / linelength=32 location=inside across=1 position=topright;
xaxis display=(nolabel);
run;
EDIT: Within SGPLOT and the VBOX statement, you can also plot the median as the line, and the mean as a point on the box plot, without any other manual calculations ahead of time. This is available as of SAS 9.4 M5+.
ods graphics / reset ANTIALIASMAX=5300 width=5in height=3in imagename='Box_Group';
title 'Cholesterol by Cause of Death';
proc sgplot data=sashelp.heart noborder;
vbox cholesterol / category=deathcause
displaystats=(median mean)
meanattrs=(color=red)
medianattrs=(color=green);
*xaxis display=(nolabel);
run;

SAS code. How to plot the dynamic of the variable y over x in SAS (the easiest way!)

How to plot the dynamic of the variable y over x in SAS (the easiest way!), for example, temperature changes over time. Thank you very much! (PC-SAS)
Two common ways are the scatter and series statements in Proc SGPLOT.
For example:
data have;
do time = 0 to 24;
time = time + ranuni(123) - 1.2;
temp = 60 + 6 * sin(time / 7.6);
rowNumber + 1;
output;
end;
run;
ods graphics on / width=325px;
proc sgplot data=have;
title "Scatter";
footnote "Created: &sysdate";
scatter x=time y=temp;
run;
proc sgplot data=have;
title "Series";
footnote "Created: &sysdate";
series x=time y=temp / markers;
run;

SAS---how to create histograms plot with specific bin in certain range

I attempt to crate histograms plot via proc univariate. The target is to crate the distribution with bins of 0.1 width from 0 to 1.5 and then all the remaining in one bin.
I applied the following code to identify the range from 0 to 1.5, while it cannot manage the rest. How can I correct the code?
proc univariate data=HAVE;
where pred between 0 and 1.5;
var pred;
histogram pred/ vscale=percent midpoints=0 to 2 by 0.1 normal (noprint);
run;
You can try something like the following code to combine two Histograms by creating two variables from one variable:
/*Temporary DS with values ranging from 01. to 2.0*/
data have;
do i=0.1 to 2.0 by 0.1;
output;
end;
rename i=pred;
run;
/*Creating two variables x(0.1-1.5) and y(1.6-2.0)*/
data have;
set have;
if pred<1.6 then x=pred;
else y=pred;
drop pred;
run;
/*Combine two Histograms*/
proc sgplot data=have;
histogram x / nbins=15 binwidth=0.1;
density x / type=normal;
histogram y / nbins=5 binwidth=1.0;
density y / type=normal;
keylegend / location=inside position=topright noborder across=2;
xaxis display=(nolabel) values=(0.1 to 2.5 by 0.1);
run;
Create your own groups
Create a format so it shows the way you'd like
Plot it with SGPLOT
*create your own groups for data, especially the last group;
data mileage;
set sashelp.cars;
mpg_group=floor(mpg_highway / 10);
if mpg_group in (5, 6, 7) then
mpg_group=5;
keep mpg_highway mpg_group;
run;
*format to control display;
proc format;
value mpg_fmt 1='0 to 10' 2='11 to 20' 3='21 to 30' 4='31 to 40' 5='40+';
run;
*plot the data;
proc sgplot data=mileage;
vbar mpg_group /stat=freq barwidth=1;
format mpg_group mpg_fmt.;
run;

SAS / PROC FREQ TABLES - can I suppress frequencies and percents if frequency is less than a given value?

I'm using tagsets.excelxp in SAS to output dozens of two-way tables to an .xml file. Is there syntax that will suppress rows (frequencies and percents) if the frequency in that row is less than 10? I need to apply that in order to de-identify the results, and it would be ideal if I could automate the process rather than use conditional formatting in each of the outputted tables. Below is the syntax I'm using to create the tables.
ETA: I need those suppressed values to be included in the computation of column frequencies and percents, but I need them to be invisible in the final table (examples of options I have considered: gray out the entire row, turn the font white so it doesn't show for those cells, replace those values with an asterisk).
Any suggestions would be greatly appreciated!!!
Thanks!
dr j
%include 'C:\Users\Me\Documents\excltags.tpl';
ods tagsets.excelxp file = "C:\Users\Me\Documents\Participation_rdg_LSS_3-8.xml"
style = MonoChromePrinter
options(
convert_percentages = 'yes'
embedded_titles = 'yes'
);
title1 'Participation';
title2 'LSS-Level';
title3 'Grades 3-8';
title4 'Reading';
ods noproctitle;
proc sort data = part_rdg_3to8;
by flag_accomm flag_participation lss_nm;
run;
proc freq data = part_rdg_3to8;
by flag_accomm flag_participation;
tables lss_nm*grade_p / crosslist nopercent;
run;
ods tagsets.excelxp close;
D.Jay: Proc FREQ does not contain any options for conditionally masking cells of it's output. You can leverage the output data capture capability of the ODS system with a follow-up Proc REPORT to produce the desired masked output.
I am guessing on the roles of the lss and grade_p as to be a skill level and a student grade level respectively.
Generate some sample data
data have;
do student_id = 1 to 10000;
flag1 = ranuni(123) < 0.4;
flag2 = ranuni(123) < 0.6;
lss = byte(65+int(26*ranuni(123)));
grade = int(6*ranuni(123));
* at every third lss force data to have a low percent of grades < 3;
if mod(rank(lss),3)=0 then
do until (grade > 2 or _n_ < 0.15);
grade = int(6*ranuni(123));
_n_ = ranuni(123);
end;
else if mod(rank(lss),7)=0 then
do until (grade < 3 or _n_ < 0.15);
grade = int(6*ranuni(123));
_n_ = ranuni(123);
end;
output;
end;
run;
proc sort data=have;
by flag1 flag2;
*where lss in ('A' 'B') and flag1 and flag2; * remove comment to limit amount of output during 'learning the code' phase;
run;
Perform the Proc FREQ
Only capture the data corresponding to the output that would have been generated
ods _all_ close;
* ods trace on;
/* trace will log the Output names
* that a procedure creates, and thus can be captured
*/
ods output CrossList=crosslist;
proc freq data=have;
by flag1 flag2;
tables lss * grade / crosslist nopercent;
run;
ods output close;
ods trace off;
Now generate output to your target ODS destination (be it ExcelXP, html, pdf, etc)
Reference output of which needs to be produced an equivalent having masked values.
* regular output of FREQ, to be compare to masked output
* of some information via REPORT;
proc freq data=have;
by flag1 flag2;
tables lss * grade / crosslist nopercent;
run;
Proc REPORT has great features for producing conditional output. The compute block is used to select either a value or a masked value indicator for output.
options missing = ' ';
proc format;
value $lss_report ' '= 'A0'x'Total';
value grade_report . = 'Total';
value blankfrq .b = '*masked*' ._=' ' other=[best8.];
value blankpct .b = '*masked*' ._=' ' other=[6.2];
proc report data=CrossList;
by flag1 flag2;
columns
('Table of lss by grade'
lss grade
Frequency RowPercent ColPercent
FreqMask RowPMask ColPMask
)
;
define lss / order order=formatted format=$lss_report. missing;
define grade / display format=grade_report.;
define Frequency / display noprint;
define RowPercent / display noprint;
define ColPercent / display noprint;
define FreqMask / computed format=blankfrq. 'Frequency' ;
define RowPMask / computed format=blankpct. 'Row/Percent';
define ColPMask / computed format=blankpct. 'Column/Percent';
compute FreqMask;
if 0 <= RowPercent < 10
then FreqMask = .b;
else FreqMask = Frequency;
endcomp;
compute RowPMask;
if 0 <= RowPercent < 10
then RowPMask = .b;
else RowPMask = RowPercent;
endcomp;
compute ColPMask;
if 0 <= RowPercent < 10
then ColPMask = .b;
else ColPMask = ColPercent;
endcomp;
run;
ods html close;
If you have to produce lots of cross listings for different data sets, the code is easily macro-ized.
When I've done this in the past, I've first generated the frequency to a dataset, then filtered out the N, then re-printed the dataset (using tabulate usually).
If you can't recreate the frequency table perfectly from the freq output, you can do a simple frequency, check which IDs or variables or what have you to exclude, and then filter them out from the input dataset and rerun the whole frequency.
I don't believe that you can with PROC FREQ, but you can easily replicate your code with PROC TABULATE and you can use a custom format there to mask the numbers. This example sets it to M for missing and N for less than 5 and with one decimal place for the rest of the values. You could also replace the M/N with a space (single space) to have no values shown instead.
*Create a format to mask values less than 5;
proc format;
value mask_fmt
. = 'M' /*missing*/
low - < 5='N' /*less than 5 */
other = [8.1]; /*remaining values with one decimal place*/
run;
*sort data for demo;
proc sort data=sashelp.cars out=cars;
by origin;
run;
ods tagsets.excelxp file='/folders/myfolders/demo.xml';
*values partially masked;
proc tabulate data=cars;
where origin='Asia';
by origin;
class make cylinders;
table make, cylinders*n*f=mask_fmt. ;
run;
ods tagsets.excelxp close;
This was tested on SAS UE.
EDIT: Forgot the percentage piece, so this likely will not work for that, primarily because I don't think you'll get the percentages the same as in PROC FREQ (appearance) so it depends on how important that is to you. The other possibility to accomplish this would be to modify the PROC FREQ template to use the custom format as above. Unfortunately I do not have time to mock this up for you but maybe someone else can. I'll leave this here to help get you started and delete it later on.