View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math4.legacy.stat.correlation;
18  
19  import java.util.Arrays;
20  
21  import org.apache.commons.math4.legacy.TestUtils;
22  import org.apache.commons.math4.legacy.linear.BlockRealMatrix;
23  import org.apache.commons.math4.legacy.linear.RealMatrix;
24  import org.apache.commons.rng.UniformRandomProvider;
25  import org.apache.commons.rng.simple.RandomSource;
26  import org.junit.Assert;
27  import org.junit.Before;
28  import org.junit.Test;
29  
30  /**
31   * Test cases for Kendall's Tau rank correlation.
32   */
33  public class KendallsCorrelationTest extends PearsonsCorrelationTest {
34  
35      private KendallsCorrelation correlation;
36  
37      @Before
38      public void setUp() {
39          correlation = new KendallsCorrelation();
40      }
41  
42      /**
43       * Test Longley dataset against R.
44       */
45      @Override
46      @Test
47      public void testLongley() {
48          RealMatrix matrix = createRealMatrix(longleyData, 16, 7);
49          KendallsCorrelation corrInstance = new KendallsCorrelation(matrix);
50          RealMatrix correlationMatrix = corrInstance.getCorrelationMatrix();
51          double[] rData = new double[] {
52                  1, 0.9166666666666666, 0.9333333333333332, 0.3666666666666666, 0.05, 0.8999999999999999,
53                  0.8999999999999999, 0.9166666666666666, 1, 0.9833333333333333, 0.45, 0.03333333333333333,
54                  0.9833333333333333, 0.9833333333333333, 0.9333333333333332, 0.9833333333333333, 1,
55                  0.4333333333333333, 0.05, 0.9666666666666666, 0.9666666666666666, 0.3666666666666666,
56                  0.45, 0.4333333333333333, 1, -0.2166666666666666, 0.4666666666666666, 0.4666666666666666, 0.05,
57                  0.03333333333333333, 0.05, -0.2166666666666666, 1, 0.05, 0.05, 0.8999999999999999, 0.9833333333333333,
58                  0.9666666666666666, 0.4666666666666666, 0.05, 1, 0.9999999999999999, 0.8999999999999999,
59                  0.9833333333333333, 0.9666666666666666, 0.4666666666666666, 0.05, 0.9999999999999999, 1
60          };
61          TestUtils.assertEquals("Kendall's correlation matrix", createRealMatrix(rData, 7, 7), correlationMatrix, 10E-15);
62      }
63  
64      /**
65       * Test R swiss fertility dataset.
66       */
67      @Test
68      public void testSwiss() {
69          RealMatrix matrix = createRealMatrix(swissData, 47, 5);
70          KendallsCorrelation corrInstance = new KendallsCorrelation(matrix);
71          RealMatrix correlationMatrix = corrInstance.getCorrelationMatrix();
72          double[] rData = new double[] {
73                  1, 0.1795465254708308, -0.4762437404200669, -0.3306111613580587, 0.2453703703703704,
74                  0.1795465254708308, 1, -0.4505221560842292, -0.4761645631778491, 0.2054604569820847,
75                  -0.4762437404200669, -0.4505221560842292, 1, 0.528943683925829, -0.3212755391722673,
76                  -0.3306111613580587, -0.4761645631778491, 0.528943683925829, 1, -0.08479652265379604,
77                  0.2453703703703704, 0.2054604569820847, -0.3212755391722673, -0.08479652265379604, 1
78          };
79          TestUtils.assertEquals("Kendall's correlation matrix", createRealMatrix(rData, 5, 5), correlationMatrix, 10E-15);
80      }
81  
82      @Test
83      public void testSimpleOrdered() {
84          final int length = 10;
85          final double[] xArray = new double[length];
86          final double[] yArray = new double[length];
87          for (int i = 0; i < length; i++) {
88              xArray[i] = i;
89              yArray[i] = i;
90          }
91          Assert.assertEquals(1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
92      }
93  
94      @Test
95      public void testSimpleReversed() {
96          final int length = 10;
97          final double[] xArray = new double[length];
98          final double[] yArray = new double[length];
99          for (int i = 0; i < length; i++) {
100             xArray[length - i - 1] = i;
101             yArray[i] = i;
102         }
103         Assert.assertEquals(-1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
104     }
105 
106     @Test
107     public void testSimpleOrderedPowerOf2() {
108         final int length = 16;
109         final double[] xArray = new double[length];
110         final double[] yArray = new double[length];
111         for (int i = 0; i < length; i++) {
112             xArray[i] = i;
113             yArray[i] = i;
114         }
115         Assert.assertEquals(1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
116     }
117 
118     @Test
119     public void testSimpleReversedPowerOf2() {
120         final int length = 16;
121         final double[] xArray = new double[length];
122         final double[] yArray = new double[length];
123         for (int i = 0; i < length; i++) {
124             xArray[length - i - 1] = i;
125             yArray[i] = i;
126         }
127         Assert.assertEquals(-1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
128     }
129 
130     @Test
131     public void testSimpleJumble() {
132         //                                     A    B    C    D
133         final double[] xArray = new double[] {1.0, 2.0, 3.0, 4.0};
134         final double[] yArray = new double[] {1.0, 3.0, 2.0, 4.0};
135 
136         // 6 pairs: (A,B) (A,C) (A,D) (B,C) (B,D) (C,D)
137         // (B,C) is discordant, the other 5 are concordant
138 
139         Assert.assertEquals((5 - 1) / (double) 6,
140                 correlation.correlation(xArray, yArray),
141                 Double.MIN_VALUE);
142     }
143 
144     @Test
145     public void testBalancedJumble() {
146         //                                     A    B    C    D
147         final double[] xArray = new double[] {1.0, 2.0, 3.0, 4.0};
148         final double[] yArray = new double[] {1.0, 4.0, 3.0, 2.0};
149 
150         // 6 pairs: (A,B) (A,C) (A,D) (B,C) (B,D) (C,D)
151         // (A,B) (A,C), (A,D) are concordant, the other 3 are discordant
152 
153         Assert.assertEquals(0.0,
154                 correlation.correlation(xArray, yArray),
155                 Double.MIN_VALUE);
156     }
157 
158     @Test
159     public void testOrderedTies() {
160         final int length = 10;
161         final double[] xArray = new double[length];
162         final double[] yArray = new double[length];
163         for (int i = 0; i < length; i++) {
164             xArray[i] = i / 2;
165             yArray[i] = i / 2;
166         }
167         // 5 pairs of points that are tied in both values.
168         // 16 + 12 + 8 + 4 = 40 concordant
169         // (40 - 0) / Math.sqrt((45 - 5) * (45 - 5)) = 1
170         Assert.assertEquals(1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
171     }
172 
173 
174     @Test
175     public void testAllTiesInBoth() {
176         final int length = 10;
177         final double[] xArray = new double[length];
178         final double[] yArray = new double[length];
179         Assert.assertEquals(Double.NaN, correlation.correlation(xArray, yArray), 0);
180     }
181 
182     @Test
183     public void testAllTiesInX() {
184         final int length = 10;
185         final double[] xArray = new double[length];
186         final double[] yArray = new double[length];
187         for (int i = 0; i < length; i++) {
188             xArray[i] = i;
189         }
190         Assert.assertEquals(Double.NaN, correlation.correlation(xArray, yArray), 0);
191     }
192 
193     @Test
194     public void testAllTiesInY() {
195         final int length = 10;
196         final double[] xArray = new double[length];
197         final double[] yArray = new double[length];
198         for (int i = 0; i < length; i++) {
199             yArray[i] = i;
200         }
201         Assert.assertEquals(Double.NaN, correlation.correlation(xArray, yArray), 0);
202     }
203 
204     @Test
205     public void testSingleElement() {
206         final int length = 1;
207         final double[] xArray = new double[length];
208         final double[] yArray = new double[length];
209         Assert.assertEquals(Double.NaN, correlation.correlation(xArray, yArray), 0);
210     }
211 
212     @Test
213     public void testTwoElements() {
214         final double[] xArray = new double[] {2.0, 1.0};
215         final double[] yArray = new double[] {1.0, 2.0};
216         Assert.assertEquals(-1.0, correlation.correlation(xArray, yArray), Double.MIN_VALUE);
217     }
218 
219     @Test
220     public void test2dDoubleArray() {
221         final double[][] input = new double[][] {
222                 new double[] {2.0, 1.0, 2.0},
223                 new double[] {1.0, 2.0, 1.0},
224                 new double[] {0.0, 0.0, 0.0}
225         };
226 
227         final double[][] expected = new double[][] {
228                 new double[] {1.0, 1.0 / 3.0, 1.0},
229                 new double[] {1.0 / 3.0, 1.0, 1.0 / 3.0},
230                 new double[] {1.0, 1.0 / 3.0, 1.0}};
231 
232         Assert.assertEquals(correlation.computeCorrelationMatrix(input),
233                 new BlockRealMatrix(expected));
234     }
235 
236     @Test
237     public void testBlockMatrix() {
238         final double[][] input = new double[][] {
239                 new double[] {2.0, 1.0, 2.0},
240                 new double[] {1.0, 2.0, 1.0},
241                 new double[] {0.0, 0.0, 0.0}
242         };
243 
244         final double[][] expected = new double[][] {
245                 new double[] {1.0, 1.0 / 3.0, 1.0},
246                 new double[] {1.0 / 3.0, 1.0, 1.0 / 3.0},
247                 new double[] {1.0, 1.0 / 3.0, 1.0}};
248 
249         Assert.assertEquals(
250                 correlation.computeCorrelationMatrix(new BlockRealMatrix(input)),
251                 new BlockRealMatrix(expected));
252     }
253 
254     @Test
255     public void testLargeArray() {
256         // test integer overflow detected in MATH-1068
257         double[] xArray = new double[100000];
258         Arrays.fill(xArray, 0, 2500, 1.0);
259 
260         Assert.assertEquals(1.0, correlation.correlation(xArray, xArray), 1e-6);
261     }
262 
263     @Test
264     public void testMath1277() {
265         // example that led to a correlation coefficient outside of [-1, 1]
266         // due to a bug reported in MATH-1277
267         UniformRandomProvider rng = RandomSource.WELL_1024_A.create(0);
268         double[] xArray = new double[120000];
269         double[] yArray = new double[120000];
270         for (int i = 0; i < xArray.length; ++i) {
271             xArray[i] =  rng.nextDouble();
272         }
273         for (int i = 0; i < yArray.length; ++i) {
274             yArray[i] =  rng.nextDouble();
275         }
276         double coefficient = correlation.correlation(xArray, yArray);
277         Assert.assertTrue(1.0 >= coefficient && -1.0 <= coefficient);
278     }
279 }