Name the form and lay out the first row of its outer table. The first column will hold the raw pairs of input data. After a separator, remaining columns will display data based on these columns.
Rank Order Correlation Coefficient ("rho") of Two Measurements
<!--- Set defaults --->
<cfparam name="form.Xraw" default="">
<cfparam name="form.Yraw" default="">
<cfset form.Xrank="">
<cfset form.Yrank="">
<cfset form.Diff="">
<cfset form.DiffSquared="">
<!--- Begin form and overall table --->
<form name="Ranks" action="rho.cfm" method="post">
<input type="submit" name="doit" value="Submit">
<table border="1">
<tr><td>RAW PAIRS</td>
<td bgcolor="LightGrey"><hr width="0" height="0"></td>
<td>ORDERED</td>
<td>X RANK</td><td>Y RANK</td>
<td>DIFF "D"</td><td>D SQUARED</td></tr>
<!--- Begin inner table for raw data ---> <tr><td> <table> <tr><td>X</td><td>Y</td></tr> <!--- Show X raw data ---> <tr><td><textarea name="Xraw" wrap="physical" rows="25" cols="3"> <cfoutput>#trim(form.Xraw)#</cfoutput></textarea><br><hr></td> <!--- Store X raw data ---> <cfset XrawPoints=ArrayNew(1)> <cfset XrawCount=0> <cfloop list="#form.Xraw#" index="Value" delimiters=" #chr(10)##chr(13)#"> <cfset XrawCount=XrawCount+1> <cfset XrawPoints[XrawCount]=val(Value)> </cfloop> <!--- Show Y raw data; end inner table ---> <td><textarea name="Yraw" wrap="physical" rows="25" cols="3"> <cfoutput>#trim(form.Yraw)#</cfoutput></textarea><br><hr></td></tr> </table> </td> <!--- Store Y raw data ---> <cfset YrawPoints=ArrayNew(1)> <cfset YrawCount=0> <cfloop list="#form.Yraw#" index="Value" delimiters=" #chr(10)##chr(13)#"> <cfset YrawCount=YrawCount+1> <cfset YrawPoints[YrawCount]=val(Value)> </cfloop>
<!--- Stop if columns aren't ready --->
<cfif XrawCount neq YrawCount>
</table></table>
Cannot proceed until the X and Y raw score columns have have the same number of values.
<cfabort>
</cfif>
<!--- Make, then sort triplets like 000X:{1000+Seq}:000Y by X alone --->
<cfset Seq=1000+YrawCount>
<cfset Xlist="">
<cfloop from="1" to="#YrawCount#" index="Point">
<cfset Seq=Seq-1>
<cfset Entry="#numberFormat(XrawPoints[Point], "0000")#:#Seq#:#numberFormat(YrawPoints[Point], "0000")#">
<cfset Xlist=listAppend(Xlist, Entry)>
</cfloop>
<cfset Xsort=listSort(Xlist, "text", "desc")>
<!--- Separate input from processed data ---> <td bgcolor="LightGrey"><hr height="0" width="0"></td> <!--- Format pairs for display; store X values for manipulation ---> <cfset Xord=""> <cfset form.ShowByX=""> <cfloop list="#Xsort#" index="Pair"> <cfset form.ShowByX=listAppend(form.ShowByX, "#val(listGetAt(Pair,1,":"))#~#val(listGetAt(Pair,3,":"))#", "#chr(10)#")> <cfset Xord=listAppend(Xord,"#val(listGetAt(Pair,1,":"))#")> </cfloop> <!--- Display sorted pairs ---> <td> <table> <tr><td>by X</td></tr> <tr><td><textarea name="ShowByX" wrap="physical" rows="25" cols="6"> <cfoutput>#trim(form.ShowByX)#</cfoutput></textarea><br><hr></td></tr> </table> </td>
Once this is done, formatting and displaying the ranks by X is similar to the process used earlier.
<!--- Get X Rank ---> <cfset Xarray=ArrayNew(1)> <cfset Row=1> <cfset Max=Listlen(Xord)> <cfloop condition="Row le Max"> <!--- Get value to be ranked ---> <cfset Seek=val(listGetAt(Xord,Row))> <!--- Count the duplicates ---> <cfset NrSame=(listValueCount(Xord,"#Seek#"))> <!--- Sum the like row numbers ---> <cfset LikeRankSum=0> <cfset LastLike=Row+NrSame-1> <cfloop from="#Row#" to="#LastLike#" index="RawRank"> <cfset LikeRankSum=LikeRankSum+RawRank> </cfloop> <!--- Divide by the number of duplicates ---> <cfset Rank=LikeRankSum/NrSame> <!--- Post to matching rows ---> <cfloop condition="#Row# le #LastLike#"> <cfset Xarray[Row]=Rank> <cfset Row=Row+1> </cfloop> <!--- Continue until all rows have been processed ---> </cfloop> <!--- Format X rank ---> <cfloop from="1" to="#listLen(Xord)#" index="Row"> <cfset form.Xrank=listAppend(form.Xrank, "#Xarray[Row]#", "#chr(10)#")> </cfloop> <td> <table> <tr> <td> 1..N </td> <tr> <td><textarea name="Xrank" wrap="physical" rows="25" cols="6"> <cfoutput>#trim(form.Xrank)#</cfoutput></textarea><br><hr></td> </tr> </table> <td> <table> <tr>
<cfset Ymake=""> <cfset Row=1000> <cfloop list="#Xsort#" index="Pair"> <cfset Row=Row+1> <cfset Ymake=listAppend(Ymake, "#numberFormat(listGetAt(Pair,3,":"),'0000')#:#Row#")> </cfloop> <cfset Ysort=listSort(Ymake, "text", "desc")> <!--- Store Y and Row values for manipulation ---> <cfset Yord=""> <cfset Yrealrow=""> <cfloop list="#Ysort#" index="Pair"> <cfset Yord=listAppend(Yord,"#val(listGetAt(Pair,1,":"))#")> <cfset Yrealrow=listAppend(Yrealrow,"#evaluate(val(listGetAt(Pair,2,":"))-1000)#")> </cfloop> <!--- Get Y Rank ---> <cfset Yarray=ArrayNew(1)> <cfset Row=1> <cfset Max=Listlen(Yord)> <cfloop condition="Row le Max"> <!--- Get value to be ranked ---> <cfset Seek=val(listGetAt(Yord,Row))> <!--- Count the duplicates ---> <cfset NrSame=(listValueCount(Yord,"#Seek#"))> <!--- Sum the like row numbers ---> <cfset LikeRankSum=0> <cfset LastLike=Row+NrSame-1> <cfloop from="#Row#" to="#LastLike#" index="RawRank"> <cfset LikeRankSum=LikeRankSum+RawRank> </cfloop> <!--- Divide by the number of duplicates ---> <cfset Rank=LikeRankSum/NrSame> <!--- Post to matching rows ---> <cfloop condition="#Row# le #LastLike#"> <cfset Yarray[listGetAt(YrealRow,Row)]=Rank> <cfset Row=Row+1> </cfloop> <!--- Continue until all rows have been processed ---> </cfloop> <!--- Format Y rank ---> <cfloop from="1" to="#listLen(Yord)#" index="Row"> <cfset form.Yrank=listAppend(form.Yrank, "#Yarray[Row]#", "#chr(10)#")> </cfloop> <td> 1..N </td> <tr> <td><textarea name="Yrank" wrap="physical" rows="25" cols="6"> <cfoutput>#trim(form.Yrank)#</cfoutput></textarea><br><hr></td> </tr> </table> </td> <td> <table> <tr> <td> 1..N </td> <tr>
<cfset Diffs=""> <cfloop from="1" to="#listLen(Yord)#" index="Row"> <cfset DiffVal=Xarray[Row]-Yarray[Row]> <cfset Diffs=listAppend(Diffs, DiffVal,"#chr(10)#")> </cfloop> <cfset form.Diff=Diffs> <td><textarea name="Diff" wrap="physical" rows="25" cols="6"> <cfoutput>#trim(form.Diff)#</cfoutput></textarea><br><hr> </td> </tr> </table> </td> <td> <table> <tr> <td> 1..N </td>
<cfset DiffSqs=""> <cfset DiffSqSum=0> <cfloop from="1" to="#listLen(Yord)#" index="Row"> <cfset DiffSq=listGetAt(Diffs,Row, "#chr(10)#")*listGetAt(Diffs,Row, "#chr(10)#")> <cfset DiffSqSum=DiffSqSum+DiffSq> <cfset DiffSqs=listAppend(DiffSqs, DiffSq, "#chr(10)#")> </cfloop> <cfset form.DiffSquared=DiffSqs> <tr> <td><textarea name="DiffSquared" wrap="physical" rows="25" cols="9"> <cfoutput>#trim(form.DiffSquared)#</cfoutput></textarea><br> Sum: <cfoutput>#DiffSqSum#</cfoutput> </td> </tr> </table> </td> <td> </tr> </table> </form>
<cfif Yrawcount lt 2> Further calculations cannot take place until at least two sets of scores have been entered. <cfabort> </cfif> <h4>Procedure to find Rho</h4> <ol> <cfset Nsquared=Yrawcount*Yrawcount> <li>Square the number of scores <cfoutput>(#Yrawcount#) yielding #Nsquared#</cfoutput>. <cfset NsquaredMinusOne=Nsquared-1> <li>Subtract one, yielding <cfoutput>#NsquaredMinusOne#</cfoutput>. <cfset Denominator=NsquaredMinusOne*Yrawcount> <li>Multiply by the number of scores, yielding <cfoutput>#Denominator#</cfoutput>: the denominator. <cfset Numerator=6*DiffSqSum> <li>Multiply the sum of the squared differences <cfoutput>(#DiffSqSum#) by six yielding #Numerator#</cfoutput>: the numerator. <cfset Ratio=Numerator/Denominator> <li>Divide the denominator into the numerator yielding a ratio of <cfoutput>#Ratio#</cfoutput>. <cfset Rho=1-Ratio> <cfset RhoRound=round(Rho*10000)/10000> <li>Subtract this from one, yielding Rho = <cfoutput>#Rho#</cfoutput> which to four decimal places rounds to <cfoutput>#RhoRound#</cfoutput>.