We’re smarter together. Learn from this collection of community knowledge and add your expertise.

SAS Studio Custom Task Tuesday: How to Improve a Basic Task

by SAS Super FREQ on ‎03-14-2017 11:05 AM - edited a week ago by Community Manager (624 Views)

CTT.jpgThis week, instead of starting over from scratch with a new task, we will be making improvements on last week's Point Estimate Calculator task. Check out last week's post for details on how to get this task started. To improve the task, we want the user to be able to select 2 variables for which to calculate estimates. We also want the user to be able to round their estimates to their desired decimal place, as well as be able to specify a where clause to subset their data.

 

Here's what it's going to look like when we're done:

 

                               BEFORE                                                                   AFTER

Original.PNG2.0.PNG

 

Adding the Optional Where Clause Textbox:

 

We want users to be able to subset their data using a where clause. For this, we will use a textbox. The texbox control has many options in Metadata with it, such as promptMessage. One that we aren't using here is missingMessage, that will be displayed in a red box if the user fails to put something in the textbox. We aren't using that option because the where clause is optional in this task. It's also helpful to attach a label to the textbox with an example as well, so they will know not to enter the "where" or the semi-colon into the box.

 

In the Code template, we surround our where clause and $textWHERE variable with an if statement, because we don't want the where clause to appear if the user hasn't typed anything. 

 

Metadata:

<Option inputType="string" name="GROUPWHERE">OPTIONAL WHERE CLAUSE</Option>
<Option inputType="string" name="labelWHERE">Enter a where clause if you would like to subset your data. Example: sex = 'F'</Option>
<Option defaultValue="" indent="1" inputType="inputtext" name="textWHERE" promptMessage="Enter a where clause" required="false">Where clause:</Option>

 

UI:

<Group open="true" option="GROUPWHERE">
    <OptionItem option="labelWHERE"/>
    <OptionItem option="textWHERE"/>
</Group>

 

Code Template: 

data copy;
	set $DATASOURCE;
	#if ($textWHERE.length() > 0) where $textWHERE; #end
run;

 

 

Adding the Optional Second Variable Role Selector:

 

We want users to be able to get point estimates for not just one variable, but two variables. To run the task, the user must select at least one variable, so in Metadata roles portion for that control we have typed minVars="1". However, the second variable is optional, so in the code for this control we have typed minVars="0". 

In the Code Template, we use a foreach to access the variable inside of the role selector. If you try to use $VAR2 without using a foreach, the variable will be in [brackets] in your code.

 

Metadata:

<DataSources> 
<DataSource name="DATASOURCE">
<Roles>
<Role maxVars="1" minVars="1" name="VAR" order="true" type="N">Variable:</Role>
<Role maxVars="1" minVars="0" name="VAR2" order="true" type="N">Optional Second Variable:</Role>
</Roles>
</DataSource>
</DataSources>UI:

 

 UI:

<Group open="true" option="ROLESGROUP">
    <RoleItem role="VAR"/>
    <RoleItem role="VAR2"/>
</Group>

 

Code Template:

(The $VAR2 variable is used in other places in the code template as well, download the full code at the bottom to check those out)

#if ($VAR2.size() > 0)
#foreach ( $item2 in $VAR2 )
%let item2 = $item2;
proc means data = copy noprint;
	var $item2;
	output out = means2 (drop = _TYPE_ _FREQ_) 
	#if ($chkMEAN == 1)		mean   = &item2._mean	#end
	#if ($chkMIN == 1)		min    = &item2._min   	#end
	#if ($chkMAX == 1)		max    = &item2._max   	#end
	#if ($chkSTD == 1)		std    = &item2._std   	#end
	#if ($chkLCLM == 1)		LCLM   = &item2._LCLM  	#end
	#if ($chkUCLM == 1)		UCLM   = &item2._UCLM  	#end
	#if ($chkP25 == 1)		p25    = &item2._p25  	#end
	#if ($chkP75 == 1)		p75    = &item2._p75 	#end
;
run;
#end #end

 

 

Adding the Rounding Combobox:

 

We want the user to be able to select how many decimal places they would like their mea, upper confidence limit, and lower confidence limit rounded to. The SAS round function requires .01 if you'd like to round to 2 decimal places, but this may not be intuitive for the user. Therefore it is important to remember that with a combobox, the name="" is what is inserted into your code, and the text in between the >arrows< is what will be shown in the task.

 

Metadata:

<Option inputType="string" name="GROUPCOMBO">ROUNDING</Option>
<Option defaultValue=".0" inputType="combobox" name="roundCOMBO">Select the number of decimal places that you would like your output statistics to be rounded to.</Option>
<Option inputType="string" name="1">0</Option>
<Option inputType="string" name="0.1">1</Option>
<Option inputType="string" name="0.01">2</Option>
<Option inputType="string" name="0.001">3</Option>
<Option inputType="string" name="0.0001">4</Option>
<Option inputType="string" name="0.00001">5</Option>
<Option inputType="string" name="0.000001">6</Option>

 

UI:

<Group open="true" option="GROUPCOMBO">
    <OptionChoice option="roundCOMBO">
        <OptionItem option="1"/>
        <OptionItem option="0.1"/>
        <OptionItem option="0.01"/>
        <OptionItem option="0.001"/>
        <OptionItem option="0.0001"/>
        <OptionItem option="0.00001"/>
        <OptionItem option="0.000001"/>
    </OptionChoice>
</Group>

 

Code Template:

#if ($VAR2.size() < 0)		
data point;
	set point1;
	#if ($chkMEAN == 1)	&item._mean = round(&item._mean, $roundCOMBO); #end
	#if ($chkLCLM == 1)	&item._lclm = round(&item._lclm, $roundCOMBO); #end
	#if ($chkUCLM == 1)	&item._uclm = round(&item._uclm, $roundCOMBO); #end
run;
#end

#if ($VAR2.size() > 0)		
data point2;
	set copy;
	if _n_ = 1 then
		set means2;
run;
data point;
	merge point1 point2;
	#if ($chkMEAN == 1)	&item._mean = round(&item._mean, $roundCOMBO); #end
	#if ($chkLCLM == 1)	&item._lclm = round(&item._lclm, $roundCOMBO); #end
	#if ($chkUCLM == 1)	&item._uclm = round(&item._uclm, $roundCOMBO); #end
	#if ($chkMEAN == 1)	&item2._mean = round(&item2._mean, $roundCOMBO); #end
	#if ($chkLCLM == 1)	&item2._lclm = round(&item2._lclm, $roundCOMBO); #end
    #if ($chkUCLM == 1)	&item2._uclm = round(&item2._uclm, $roundCOMBO); #end
run;
#end

 

 

You did it!

 

We've made significant improvements to the Point Estimate Calculator task that make it easier to use and much more functional. Click the save.pngbutton to save, then click the run.pngbutton to open the task. Make your selections, then click run.pngagain to watch it run!

 

Want to try it yourself?

Get the code from the zip file at the end of this article or from GitHub. 

Take Me to GitHub!

Attachment
Your turn
Sign In!

Want to write an article? Sign in with your profile.


Looking for the Ask the Expert series? Find it in its new home: communities.sas.com/askexpert.