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

Custom Task Tuesday: Power Analysis for One Way Anova

by SAS Employee OliviaWright on ‎04-25-2017 01:08 PM (1,213 Views)

SAS Studio has several built-in tasks for power and sample size calculations for different types of analyses, including pearson correlation, multiple regression, confidence intervals, t-tests, and more. However, there are a few other test options under proc power that are not covered under these built-in tasks. One of them is the onewayanova option. 

 

 power.PNG

 

 

 

 

 

 

 

 

 

This week we will create a task that calculates power and sample size for a One Way Anova test. Some of the options are the same as the options for the Pearson Correlation task that is already built-in in SAS Studio (Solve For group, Sample Size group, Alpha group, etc.). I started from the Pearson Correlation task, deleted everything I didn't need, and added in the functionality that is specific to one way anova. Another option would've been to start from a brand new task and copy over the things you need from the Pearson Correlation task. Whatever works for you is fine!

 

This task relies heavily on knowledge of Option Tables as well as the Requirements portion of the VTL Code. For more background information on those, see last week's post.

 

Here's what the finished task will look like:

anova power.PNG

 

Example Code from the Metadata Portion

 

As stated earlier, the most important metadata controller in this task is the option table. Here is the code for two of the Option Tables I wrote (that weren't in the original Pearson Correlation task), the Group Means option table and the Group Weights option table:

 

<Option inputType="string" name="groupMeansGroup">GROUP MEANS</Option> 
    <OptionTable addRemoveRowTools="true" initialNumberOfRows="2" label="Group mean values:" minimumRequiredRows="2" name="groupMeansTable" noIncompleteRows="true" showColumnHeadings="false">
        <Columns>
            <Column label="Group Means" name="groupMeans">
                <Option decimalPlaces="0,15" inputType="numbertext" invalidMessage="Enter an integer for group means" missingMessage="Enter an integer for group means" promptMessage="Enter an integer for group means" rangeMessage="Enter an integer for group means" required="true"/>
            </Column>
        </Columns>
    </OptionTable>
<OptionTable addRemoveRowTools="true" initialNumberOfRows="1" label="Group weight values:" minimumRequiredRows="0" name="weightsTable" noIncompleteRows="true" showColumnHeadings="false"> <Columns> <Column label="Group Weights" name="weights"> <Option decimalPlaces="0,15" inputType="numbertext" invalidMessage="Enter an integer for group weights" missingMessage="Enter an integer for group weights" promptMessage="Enter an integer for group weights" rangeMessage="Enter an integer for group weights" required="false"/> </Column> </Columns> </OptionTable>

 

There's nothing new or exciting in the UI portion of the task that hasn't already been covered in this series, so we are going to skip that. Download the full task (by visiting the GitHub link at the bottom of the post) to view the full code.

 

Example Code from the Dependencies Portion

 

For the one way anova, there are two options for test: overall and contrast. Each of them have different subsequent options that will be specified in the proc. Dependencies allow you to hide/show or disable/enable controllers based on a condition. We want to show all of the the contrastGroup, nullContrastGroup, and sides options on the condition that the comboTest is 'contrast,' and we want to had all of those options on the condition that the comboTest is not 'contrast.'

 

Here's the Dependency code that does that:

 

<Dependency condition="($comboTEST == 'contrast')">
    <Target action="show" conditionResult="true" option="contrastGroup"/>
    <Target action="hide" conditionResult="false" option="contrastGroup"/>
    <Target action="show" conditionResult="true" option="nullContrastGroup"/>
    <Target action="hide" conditionResult="false" option="nullContrastGroup"/>
    <Target action="show" conditionResult="true" option="sides"/>
    <Target action="hide" conditionResult="false" option="sides"/>
</Dependency>

 

 

Example Code from the Requirements Portion

 

The Requirements portion allows you to specfiy a condition that must be true in order for the code to generate and each requirement can include multiple controls. One quirky thing about the requirements conditions is that you must use &amp;&amp; to create a condition with an "and."

 

Below are the two requirements I wrote in addition to the ones that I used from the Pearson Correlation task. The first specifies that if the test is contrast, the number of values for group means must be the same as the number of values for contrasts. The second specfies that if the group weights table is not empty, the number of values in the group weights table must be the same number of values in the group means table.

 

<Requirement condition="!(  !($comboTEST=='overall') &amp;&amp; !($groupMeansTable.columns.groupMeans.numValues == $contrastTable.columns.contrast.numValues))">
    <Message nlsKey="meansContrastKey">There must be the same number of values for group means and contrast.</Message>
</Requirement>
<Requirement condition="!(  !($weightsTable.columns.weights.numValues == 0) &amp;&amp; !($weightsTable.columns.weights.numValues == $groupMeansTable.columns.groupMeans.numValues))">
    <Message nlsKey="weightsKey">There must be the same number of values for group means and group weights.</Message>
</Requirement>

 

 

Full Code Template Portion

 

Below is the full code template portion of the task. As I specified in last week's post, there is a unique way to access values from an option table, so that is the majority of the code below. All of the PLOTS section of the code is reused from the built-in Pearson Correlation task.

 

ods noproctitle;
#if ($powerBySampleSizePlot == 1 || (
            ($powerByEffectPlot && $powerByEffectPlot == 1) ||
            ($sampleSizeByEffectPlot && $sampleSizeByEffectPlot == 1) 
            ))
ods graphics / imagemap=on;
#end

proc power;
   onewayanova test=$comboTEST stddev=$numberSTDDEV

## group means list
#set($_groupMeans=[])
#foreach($item in $groupMeansTable.rows.values)
   #if ($item.groupMeans)
      #set($_dummy=$_groupMeans.add("$item.groupMeans"))
   #end
#end
#if ($_groupMeans.size() > 1) groupmeans=#foreach($item in $_groupMeans)$item #if($velocityCount < $_groupMeans.size()) | #end#end#end

## contrast list
#set($_contrast=[])
#foreach($item in $contrastTable.rows.values)
   #if ($item.contrast)
      #set($_dummy=$_contrast.add("$item.contrast"))
   #end
#end
#if ($_contrast.size() > 1) contrast=(#foreach($item in $_contrast)$item #if($velocityCount < $_contrast.size()) #end#end )#end 

## null contrast list
#set($_nullContrast=[])
#foreach($item in $nullContrastTable.rows.values)
   #if ($item.nullContrast)
      #set($_dummy=$_nullContrast.add("$item.nullContrast"))
   #end
#end
#if ($_nullContrast.size() > 0) nullcontrast= #foreach($item in $_nullContrast)$item #if($velocityCount < $_nullContrast.size()) #end#end#end 

## group n list
#set($_groupNs=[])
#foreach($item in $groupNsTable.rows.values)
   #if ($item.groupNs)
      #set($_dummy=$_groupNs.add("$item.groupNs"))
   #end
#end
#if ($_groupNs.size() > 1) groupns=(#foreach($item in $_groupNs)$item #if($velocityCount < $_groupNs.size()) #end#end )#end 

## n per group list
#set($_nPerGroup=[])
#foreach($item in $nPerGroupTable.rows.values)
   #if ($item.nPerGroup)
      #set($_dummy=$_nPerGroup.add("$item.nPerGroup"))
   #end
#end
#if ($_nPerGroup.size() > 0) npergroup= #foreach($item in $_nPerGroup)$item #if($velocityCount < $_nPerGroup.size()) #end#end#end 
#if ($comboTEST == 'contrast')
sides=#if ($sides == 'sidesOne')1
	#elseif($sides == 'sidesTwo')2
	#elseif($sides == 'sidesLower')L
	#elseif($sides == 'sidesUpper')U
	#end
#end
#if ($solveFor == 'solveforPowerChoice')
  	## sample size list
   	#set($_totalN=[])
   	#if (!($nfractional == 1)) 
         #set($ssTable=$totalNTable)
   	#else #set($ssTable=$fractionalTotalNTable)
   	#end
   	#foreach($item in $ssTable.rows.values)
      	#if ($item.totalN)
          	#set($_dummy=$_totalN.add("$item.totalN"))
      	#end
   	#end
   	#if ($_totalN.size() > 0) ntotal=#foreach($item in $_totalN) $item#end#end
#elseif ($solveFor == 'solveforSampSizeChoice')
    ## Power
    #set($_power=[])
    #foreach($item in $powerTable.rows.values)
        #if ($item.power)
            #set($_dummy=$_power.add("$item.power"))
        #end
    #end
    #if ($_power.size() > 0) power=#foreach($item in $_power) $item #end#end
#end

## group weights list
#set($_weights=[])
#foreach($item in $weightsTable.rows.values)
   #if ($item.weights)
      #set($_dummy=$_weights.add("$item.weights"))
   #end
#end
#if ($_weights.size() > 0) groupweights= (#foreach($item in $_weights)$item #end ) #end 

## Alpha
#set($_alpha=[])
#foreach($item in $alphaTable.rows.values)
   #if ($item.alpha)
      #set($_dummy=$_alpha.add("$item.alpha"))
   #end
#end
#if ($_alpha.size() > 0) alpha=#foreach($item in $_alpha) $item#end#end

#if ($nfractional == 1) nfractional#end   

#if ($solveFor == 'solveforPowerChoice')
 power=.
#elseif ($solveFor == 'solveforSampSizeChoice')
 ntotal=.
 #end
;

##### PLOTS #####
#if (!($sampParam == 'sampParam3'))
#if ($powerBySampleSizePlot == '1')
plot
   #if ($solveFor == 'solveforPowerChoice') x=n 
      #if ($usePlotMinSSValue == '1') min=$ssMinValue#end
      #if ($usePlotMaxSSValue == '1') max=$ssMaxValue#end
   #else x=power
      #if ($usePlotMinPowerValue == '1') min=$powerMinValue#end
      #if ($usePlotMaxPowerValue == '1') max=$powerMaxValue#end
   #end
;
#end
#if (($sampleSizeByEffectPlot && $sampleSizeByEffectPlot == 1) || ($powerByEffectPlot && $powerByEffectPlot == 1) )
   plot x=effect
      #if ($usePlotMinEffectValue == '1') min=$corrMinValue#end
      #if ($usePlotMaxEffectValue == '1') max=$corrMaxValue#end
   ;
#end
#end
##### End of PLOTS #####
run;

Yes, all that SAS code for just one proc! :) 

 

 

Want to try it yourself?

Visit our SAS Studio GitHub to download the code for this task and follow along. 

Take Me to GitHub!

 

Join the conversation on Twitter! Use the hashtag #CustomTaskTuesday and tweet Twitter_bird_logo_2012.svg.png@OliviaJWright with your Custom Task comments and questions!

 

Contributors
Your turn
Sign In!

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