<p><div><div><div><div data-width="100" data-show-faces="false" data-send="true" data-layout="button_count" data-height="21" data-href="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/"></div></div><div><a data-url="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/" data-counturl="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/" data-count="horizontal" data-text="Showing a different approach to making statistical tests" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="https://privefl.github.io/blog/Showing-a-different-approach-to-making-statistical-tests/"> Florian Privé</a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p></p>
<p></p>
<p></p>
<p></p>
<section>
<p>In this post, I will talk about an alternative way to choose quantiles (and more broadly, decision boundaries) for statistical tests, the ones you choose in order to have a 95% confidence interval (5% of type-I error). I will then show that this idea can be used to combine tests. I will use some illustrations in R to make this clearer.</p>
<p>I got this idea during my internship last year on comparing many goodness-of-fit test statistics for the Weibull distribution in the case of type-II right censoring.</p>
<div>
<h2>Example with the chi-squared distribution</h2>
<p>Say that you have a test whose values under the null hypothesis (<span>\(H_0\)</span>) follow a chi-squared distribution with 10 degrees of freedom (<span>\(\chi_{10}^2\)</span>).</p>
<p>You can choose either</p>
<ul>
<li>to reject <span>\(H_0\)</span> (with significance <span>\(\alpha = 5\%\)</span>) only for the largest values of the test statistic, which means rejecting the null hypothesis for values that are larger than the 95-percentile:</li>
</ul>
<div>
<img alt="One-tailed test" src="https://i2.wp.com/privefl.github.io/blog/images/post-tests/chi-squared_test2.jpg?w=456&ssl=1" data-recalc-dims="1">
<p>
One-tailed test
</p>
</div>
<ul>
<li>or to reject <span>\(H_0\)</span> for both largest and smallest values of the statistic. Indeed, smallest values could be considered “too good to be true” <span>(Stuart 1954)</span>. Then, <span>\(H_0\)</span> is rejected for values smaller than the 2.5-percentile or larger than the 97.5-percentile:</li>
</ul>
<div>
<img alt="Two-tailed test" src="https://i0.wp.com/privefl.github.io/blog/images/post-tests/chi-squared_test1.jpg?w=456&ssl=1" data-recalc-dims="1">
<p>
Two-tailed test
</p>
</div>
<p> <strong>Why choosing? Why not letting the test choose by itself?</strong></p>
<p>What do I mean by this? If you make the decision boundary on the test statistic’s density’s values (y-axis), not directly on the statistic’s values (x-axis), you always obtain a one-tailed test whatever is the distribution of the test statistic. Then, you reject <span>\(H_0\)</span> for all values that have a corresponding density lower than the 5-percentile:</p>
<div>
<img alt="Always a one-tailed test, but with respect to the y-axis" src="https://i0.wp.com/privefl.github.io/blog/images/post-tests/chi-squared_test3.jpg?w=456&ssl=1" data-recalc-dims="1">
<p>
Always a one-tailed test, but with respect to the y-axis
</p>
</div>
<p>I see this as <strong>rejecting the 5% less probable values</strong> (“probable” in terms of the test statistic’s density). This may be a way to get unbiased tests.</p>
</div>
<div>
<h2>Application to the combination of tests</h2>
<p>Combining tests may be a way to create more powerful or robust tests.</p>
<div>
<h3>First example: application in reliability</h3>
<p>Say that you have two goodness-of-fit test statistics for the Weibull distribution (GOFWs) (a well-known distribution in survival analysis). How to combine them?</p>
<p>A priori, the best way I can see is to use their joint distribution. A 2D distribution has a density, as before, so we can find a threshold so that only 5% of this distribution’s values have a corresponding density under this threshold. This threshold is also called a 95%-contour.</p>
<p>Again, an image will be clearer than words. I drew several samples of size 50 from the Weibull distribution and three alternatives to the Weibull distribution: the Gamma, Log-Normal and Dhillon I distributions. For all these samples, I computed the corresponding values of the two GOFWs, and I plotted these paired values:</p>
<p><img src="https://i0.wp.com/privefl.github.io/blog/images/post-tests/combi.jpg?w=456&ssl=1" data-recalc-dims="1"></p>
<p>So, in black are the paired values for several samples of the Weibull distribution (the null hypothesis) and the alternatives are spread around. We have also in black the 95%-contour for <span>\(H_0\)</span>. So, points outside of this boundary correspond to samples for which we reject the null hypothesis <span>\(H_0\)</span>.</p>
<p>This gave one of the most powerful tests for the Weibull distribution.</p>
<p>For an example with R code, see the second example below.</p>
</div>
<div>
<h3>Second example: application in genomics</h3>
<div>
<h4>Introduction</h4>
<p>Cochran-Armitage Trend Tests (CATT) is well used in genomics to test for association between a single marker and a disease <span>(Zheng et al. 2012, sec. 3.3.1)</span>. When the true genetic model is respectively the recessive (REC), additive (ADD), or dominant (DOM) model, the trend test ZCATT(x), where x is equal to 0, 1/2, or 1 respectively, gives powerful tests. Yet, the true model is generally unknown and choosing one specific value of x can lead to poor powers for some alternative models.</p>
<p>Then, the MAX3 statistic defined by <span>\[MAX3 = \max\{|ZCATT(0)|, |ZCATT(1/2)|, |ZCATT(1)|\}\]</span> can be used to have a more robust test (the power of the test remains good whatever is the underlying unkonwn model).</p>
<p>Yet, we could make another robust test based on the idea of the first section.</p>
</div>
<div>
<h4>Simulation of values for these three statistics</h4>
<p>I followed the algorithm detailed in <span>(Zheng et al. 2012, sec. 3.9.1)</span> to simulate contingency tables under different parameters as, for example, the genotype relative risk (GRR) <span>\(\lambda_2\)</span>, the genetic model, the minor allele frequency (MAF) <span>\(p\)</span>, etc.</p>
<div>
<pre><code><span>source</span>(<span>&quot;https://privefl.github.io/blog/code/simu_counts.R&quot;</span>)
<span>source</span>(<span>&quot;https://privefl.github.io/blog/code/ZCATT.R&quot;</span>)</code></pre>
</div>
<p>Let us plot simulated values of three statistics, ZCATT(0), ZCATT(1/2) and ZCATT(1), by pairs. I will add to these plot two decision boundaries corresponding to the rejection of the null hypothesis for the statistics <span>\(MAX2 = \max\{|S_1|, |S_2|\}\)</span> (the square) and <span>\(DENS2 = \hat{f}_{S_1, S_2}\)</span> (the oval).</p>
<div>
<pre><code><span>source</span>(<span>&quot;https://privefl.github.io/blog/code/square.R&quot;</span>)
pacman::<span>p_load</span>(ks) 

<span># Set of parameters</span>
LWD &lt;-<span> </span><span>3</span>; PCH &lt;-<span> </span><span>19</span>; CEX &lt;-<span> </span><span>0.5</span>
XLIM &lt;-<span> </span>YLIM &lt;-<span> </span><span>c</span>(-<span>3</span>, <span>3</span>)
models &lt;-<span> </span><span>c</span>(<span>&quot;NULL&quot;</span>, <span>&quot;REC&quot;</span>, <span>&quot;ADD&quot;</span>, <span>&quot;DOM&quot;</span>)
n &lt;-<span> </span><span>length</span>(models)
NSIM &lt;-<span> </span><span>200</span>
lambda2 &lt;-<span> </span><span>c</span>(<span>1.5</span>, <span>1</span>/<span>1.5</span>)
p &lt;-<span> </span><span>0.3</span>

<span># Get lots of simulated values for the three statistics under H0</span>
counts &lt;-<span> </span><span>simu_counts</span>(<span>nsim =</span> <span>1e5</span>, <span>p =</span> p)             
simus &lt;-<span> </span><span>sapply</span>(<span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), function(x) <span>ZCATT</span>(counts, <span>x =</span> x))
simus.save &lt;-<span> </span><span>replace</span>(simus, <span>is.na</span>(simus), <span>0</span>)
<span>colnames</span>(simus.save) &lt;-<span> </span><span>paste0</span>(<span>&quot;ZCATT(&quot;</span>, <span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), <span>&quot;)&quot;</span>)
  
<span># Plot by pairs </span>
for (ind in -(<span>1</span>:<span>3</span>)) {
  simus2D &lt;-<span> </span>simus.save[, ind]
  <span># DENS2</span>
  k &lt;-<span> </span>ks::<span>kde</span>(simus2D)
  <span>plot</span>(k, <span>cont =</span> <span>95</span>, <span>col =</span> n<span>+1</span>, <span>lwd =</span> LWD,
       <span>xlim =</span> XLIM, <span>ylim =</span> YLIM)
  <span># MAX2</span>
  q &lt;-<span> </span><span>quantile</span>(<span>apply</span>(<span>abs</span>(simus2D), <span>1</span>, max), <span>0.95</span>) 
  <span>square</span>(q, <span>col =</span> <span>5</span>, <span>lwd =</span> LWD)
  <span># H0 + Alternatives</span>
  for (lam2 in lambda2) {
    for (i in <span>1</span>:n) {
      counts &lt;-<span> </span><span>simu_counts</span>(<span>nsim =</span> NSIM, <span>model =</span> models[i], 
                            <span>lam2 =</span> lam2, <span>p =</span> p)
      simus &lt;-<span> </span><span>sapply</span>(<span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), function(x) <span>ZCATT</span>(counts, <span>x =</span> x))
      simus &lt;-<span> </span><span>replace</span>(simus, <span>is.na</span>(simus), <span>0</span>)[, ind]
      <span>points</span>(simus, <span>col =</span> i, <span>cex =</span> CEX, <span>pch =</span> PCH, 
             <span>lwd =</span> <span>ifelse</span>(i ==<span> </span><span>1</span>, LWD, <span>1</span>)) 
    }
  }
  <span># Legend</span>
  <span>legend</span>(<span>x =</span> <span>&quot;bottomright&quot;</span>, <span>legend =</span> models, <span>pch =</span> PCH, <span>col =</span> <span>1</span>:n)
}</code></pre>
</div>
<p><img src="https://i0.wp.com/privefl.github.io/blog/knitr_files/post-tests_files/figure-html/unnamed-chunk-6-1.png?w=456&ssl=1" data-recalc-dims="1"><img src="https://i1.wp.com/privefl.github.io/blog/knitr_files/post-tests_files/figure-html/unnamed-chunk-6-2.png?w=456&ssl=1" data-recalc-dims="1"><img src="https://i0.wp.com/privefl.github.io/blog/knitr_files/post-tests_files/figure-html/unnamed-chunk-6-3.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>Let us plot these three statistics’ values in 3D:</p>
<div>
<pre><code>pacman::<span>p_load</span>(rgl, rglwidget) 

rgl::<span>plot3d</span>(<span>x =</span> simus.save[<span>1</span>:NSIM, ], <span>size =</span> <span>5</span>, <span>xlab =</span> <span>&quot;ZCATT(0)&quot;</span>,
            <span>ylab =</span> <span>&quot;ZCATT(1/2)&quot;</span>, <span>zlab =</span> <span>&quot;ZCATT(1)&quot;</span>)
for (lam2 in lambda2) {
  for (i in <span>2</span>:<span>length</span>(models)) {
    counts &lt;-<span> </span><span>simu_counts</span>(<span>nsim =</span> NSIM, <span>p =</span> p, <span>model =</span> models[i], <span>lam2 =</span> lam2)
    simus &lt;-<span> </span><span>sapply</span>(<span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), function(x) <span>ZCATT</span>(counts, <span>x =</span> x))
    rgl::<span>plot3d</span>(<span>x =</span> simus, <span>col =</span> i, <span>add =</span> <span>TRUE</span>)
  }
}
<span>rglwidget</span>()</code></pre>
</div>
<div></div>
<p></p>
<p>We can see the three statistics’ values for the different models (H0: black, REC: red, ADD: green, DOM: blue) are almost on a same plane. So, it would be meaningless to estimate the 3D density.</p>
</div>
<div>
<h4>Comparaison of MAX3 and this new idea</h4>
<p>I rather projected these simulated values in 2D through a Principal Component Analysis and then made the new statistic with the 2D density of the first PCs:</p>
<div>
<pre><code>  <span>colnames</span>(simus.save) &lt;-<span> </span><span>NULL</span>
  pca &lt;-<span> </span><span>prcomp</span>(simus.save, <span>center =</span> <span>FALSE</span>)
  simus2D &lt;-<span> </span>pca$x[, <span>1</span>:<span>2</span>]
  <span># DENS2 on PCs</span>
  k &lt;-<span> </span>ks::<span>kde</span>(simus2D)
  <span>plot</span>(k, <span>cont =</span> <span>95</span>, <span>col =</span> n<span>+1</span>, <span>lwd =</span> LWD)
  <span># MAX3</span>
  q &lt;-<span> </span><span>quantile</span>(<span>apply</span>(<span>abs</span>(simus.save), <span>1</span>, max), <span>0.95</span>) 
  for (j in <span>1</span>:<span>3</span>) {
    cart &lt;-<span> </span>pca$rotation[j, <span>1</span>:<span>2</span>]
    <span>abline</span>(q/cart[<span>2</span>], -cart[<span>1</span>]/cart[<span>2</span>], <span>col =</span> j<span>+1</span>)
    <span>abline</span>(-q/cart[<span>2</span>], -cart[<span>1</span>]/cart[<span>2</span>], <span>col =</span> j<span>+1</span>)
  }
  <span>legend</span>(<span>x =</span> <span>&quot;topright&quot;</span>, <span>legend =</span> <span>paste0</span>(<span>&quot;ZCATT(&quot;</span>, <span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), <span>&quot;)&quot;</span>), 
         <span>lwd =</span> <span>1</span>, <span>col =</span> <span>2</span>:<span>4</span>)
  <span># H0 + Alternatives</span>
  for (lam2 in lambda2) {
    for (i in <span>1</span>:n) {
      counts &lt;-<span> </span><span>simu_counts</span>(<span>nsim =</span> NSIM, <span>model =</span> models[i], 
                            <span>lam2 =</span> lam2, <span>p =</span> p)
      simus &lt;-<span> </span><span>sapply</span>(<span>c</span>(<span>0</span>, <span>0.5</span>, <span>1</span>), function(x) <span>ZCATT</span>(counts, <span>x =</span> x))
      simus &lt;-<span> </span><span>replace</span>(simus, <span>is.na</span>(simus), <span>0</span>)
      simus &lt;-<span> </span><span>predict</span>(pca, simus)
      <span>points</span>(simus, <span>col =</span> i, <span>cex =</span> CEX, <span>pch =</span> PCH, 
             <span>lwd =</span> <span>ifelse</span>(i ==<span> </span><span>1</span>, LWD, <span>1</span>)) 
    }
  }
  <span># Legend</span>
  <span>legend</span>(<span>x =</span> <span>&quot;bottomright&quot;</span>, <span>legend =</span> models, <span>pch =</span> PCH, <span>col =</span> <span>1</span>:n)</code></pre>
</div>
<p><img src="https://i2.wp.com/privefl.github.io/blog/knitr_files/post-tests_files/figure-html/unnamed-chunk-8-1.png?w=456&ssl=1" data-recalc-dims="1"></p>
<p>The lines correspond to the decision boundaries of MAX3: for each of the 3 studied statistic, <span>\(H_0\)</span> is rejected for a point which is outside the corresponding two lines. At this point, if I made myself clear enough, you should see that the decision boundary of MAX3 on the previous plot is defined by the convex hull of the 6 lines.</p>
<p>As before, the oval represents the DENS2 statistic (here, on the two first PCs). It does give a robust test, yet slightly less powerful than MAX3. Indeed, to compare these two tests, there is no need for computing their precise powers for each alternative. You just have to compare the number of alternatives (blue, green, and red points) for which <span>\(H_0\)</span> is rejected with one test but not the other, on the plot. At the top and bottom of the plot, we can see a <strong>large</strong> region where we would reject <span>\(H_0\)</span> with DENS2 and not MAX3, yet there are <strong>not many</strong> alternatives in there. On the contrary, there are 3 <strong>small</strong> areas on the left and on the right of the plot where we would reject <span>\(H_0\)</span> with MAX3 and not DENS2, yet there are <strong>many</strong> alternatives in there.</p>
<p>The problem of DENS2 being slightly less powerful, I think, is that the 2D or 3D distributions of the statistics’ values for the alternatives are highly correlated with the ones of the null hypothesis (they have the same shape and tends to be on the same diagonal). So, even if the “area of H0” is larger with MAX2 or MAX3 than DENS2 (see all 2D plots), the number of alternatives in there is lower, so they give a more powerful test than DENS2 in this case.</p>
</div>
</div>
</div>
<div>
<h2>Conlusion</h2>
<p>We have seen how to use density to get robust and powerful tests, without any subjective choice. We have also visualized some combination of tests and directly assessed from plots the powers of tests for multiple alternatives. Yet, we have not seen how DENS1 could unbias tests (you should try it yourself).</p>
<p>In practice, this works well with approximately normally distributed statistics because it’s then easy to get a non-parametric estimation of the density via the use of a Gaussian Kernel (what does <code>kde</code>).</p>
</div>
<div>
<h2>References</h2>
<div>
<div>
<p>Stuart, Alan. 1954. “Too Good to Be True?” <em>Journal of the Royal Statistical Society. Series C (Applied Statistics)</em> 3 (1). [Wiley, Royal Statistical Society]: 29–32. <a target="_blank" href="http://www.jstor.org/stable/2985442">http://www.jstor.org/stable/2985442</a>.</p>
</div>
<div>
<p>Zheng, Gang, Yaning Yang, Xiaofeng Zhu, and Robert C. Elston. 2012. <em>Analysis of Genetic Association Studies</em>. Statistics for Biology and Health. Boston, MA: Springer US. doi:<a target="_blank" href="https://doi.org/10.1007/978-1-4614-2245-7">10.1007/978-1-4614-2245-7</a>.</p>
</div>
</div>
</div>
</section>
<p><div><div><div><div data-width="55" data-show-faces="false" data-send="true" data-layout="box_count" data-height="62" data-href="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/"></div></div><div><a data-url="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/" data-counturl="https://www.r-bloggers.com/showing-a-different-approach-to-making-statistical-tests/" data-count="vertical" data-text="Showing a different approach to making statistical tests" class="twitter-share-button" data-via="rbloggers" href="https://twitter.com/share"></a></div><div></div></div><div></div></div>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="https://privefl.github.io/blog/Showing-a-different-approach-to-making-statistical-tests/"> Florian Privé</a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a title="The R Project for Statistical Computing" rel="nofollow" href="https://www.r-project.org/">R</a> news and <a title="R tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=tutorial">tutorials</a> on topics such as: <a title="Data science" rel="nofollow" href="https://www.r-bloggers.com/?s=data%20science">Data science</a>, <a title="Big Data" rel="nofollow" href="https://www.r-bloggers.com/?s=Big%20Data">Big Data, <a title="R jobs" rel="nofollow" href="https://www.r-users.com/">R jobs</a>, visualization (<a title="ggplot and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=ggplot2">ggplot2</a>, <a title="Boxplots using lattice and ggplot2 tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=boxplot">Boxplots</a>, <a title="Maps and gis" rel="nofollow" href="https://www.r-bloggers.com/?s=map">maps</a>, <a title="Animation in R" rel="nofollow" href="https://www.r-bloggers.com/?s=animation">animation</a>), programming (<a title="RStudio IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=RStudio">RStudio</a>, <a title="Sweave and literate programming" rel="nofollow" href="https://www.r-bloggers.com/?s=sweave">Sweave</a>, <a title="LaTeX in R" rel="nofollow" href="https://www.r-bloggers.com/?s=LaTeX">LaTeX</a>, <a title="SQL and databases" rel="nofollow" href="https://www.r-bloggers.com/?s=SQL">SQL</a>, <a title="Eclipse IDE for R" rel="nofollow" href="https://www.r-bloggers.com/?s=eclipse">Eclipse</a>, <a title="git and github, Version Control System" rel="nofollow" href="https://www.r-bloggers.com/?s=git">git</a>, <a title="Large data in R using Hadoop" rel="nofollow" href="https://www.r-bloggers.com/?s=hadoop">hadoop</a>, <a title="Web Scraping of google, facebook, yahoo, twitter and more using R" rel="nofollow" href="https://www.r-bloggers.com/?s=Web+Scraping">Web Scraping</a>) statistics (<a title="Regressions and ANOVA analysis tutorials" rel="nofollow" href="https://www.r-bloggers.com/?s=regression">regression</a>, <a title="principal component analysis tutorial" rel="nofollow" href="https://www.r-bloggers.com/?s=PCA">PCA</a>, <a title="Time series" rel="nofollow" href="https://www.r-bloggers.com/?s=time+series">time series</a>, <a title="finance trading" rel="nofollow" href="https://www.r-bloggers.com/?s=trading">trading</a>) and more...
<img height="1" alt="" width="1" src="http://feeds.feedburner.com/~r/RBloggers/~4/R6_yv1kHaaI"></a></div>