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    *      https://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  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.stat.descriptive.rank;
23  
24  import java.io.Serializable;
25  
26  import org.hipparchus.exception.MathIllegalArgumentException;
27  import org.hipparchus.exception.NullArgumentException;
28  import org.hipparchus.stat.descriptive.AbstractUnivariateStatistic;
29  import org.hipparchus.stat.descriptive.rank.Percentile.EstimationType;
30  import org.hipparchus.stat.ranking.NaNStrategy;
31  import org.hipparchus.util.KthSelector;
32  
33  
34  /**
35   * Returns the median of the available values.  This is the same as the 50th percentile.
36   * See {@link Percentile} for a description of the algorithm used.
37   * <p>
38   * <strong>Note that this implementation is not synchronized.</strong> If
39   * multiple threads access an instance of this class concurrently, and at least
40   * one of the threads invokes the <code>increment()</code> or
41   * <code>clear()</code> method, it must be synchronized externally.
42   */
43  public class Median extends AbstractUnivariateStatistic implements Serializable {
44  
45      /** Serializable version identifier */
46      private static final long serialVersionUID = 20150412L;
47  
48      /** Fixed quantile. */
49      private static final double FIXED_QUANTILE_50 = 50.0;
50  
51      /** The percentile impl to calculate the median. */
52      private final Percentile percentile;
53  
54      /**
55       * Default constructor.
56       */
57      public Median() {
58          percentile = new Percentile(FIXED_QUANTILE_50);
59      }
60  
61      /**
62       * Constructs a Median with the specific {@link EstimationType},
63       * {@link NaNStrategy} and {@link KthSelector}.
64       *
65       * @param estimationType one of the percentile {@link EstimationType estimation types}
66       * @param nanStrategy one of {@link NaNStrategy} to handle with NaNs
67       * @param kthSelector {@link KthSelector} to use for pivoting during search
68       * @throws MathIllegalArgumentException if p is not within (0,100]
69       * @throws NullArgumentException if type or NaNStrategy passed is null
70       */
71      private Median(final EstimationType estimationType, final NaNStrategy nanStrategy,
72                     final KthSelector kthSelector)
73          throws MathIllegalArgumentException {
74  
75          percentile = new Percentile(FIXED_QUANTILE_50, estimationType,
76                                      nanStrategy, kthSelector);
77      }
78  
79      /**
80       * Copy constructor, creates a new {@code Median} identical
81       * to the {@code original}
82       *
83       * @param original the {@code Median} instance to copy
84       * @throws NullArgumentException if original is null
85       */
86      Median(Median original) throws NullArgumentException {
87          super(original);
88          this.percentile = original.percentile.copy();
89      }
90  
91      /** {@inheritDoc} */
92      @Override
93      public double evaluate(double[] values, int begin, int length)
94          throws MathIllegalArgumentException {
95          return percentile.evaluate(values, begin, length);
96      }
97  
98      /** {@inheritDoc} */
99      @Override
100     public Median copy() {
101         return new Median(this);
102     }
103 
104     /**
105      * Get the estimation {@link EstimationType type} used for computation.
106      *
107      * @return the {@code estimationType} set
108      */
109     public EstimationType getEstimationType() {
110         return percentile.getEstimationType();
111     }
112 
113     /**
114      * Build a new instance similar to the current one except for the
115      * {@link EstimationType estimation type}.
116      *
117      * @param newEstimationType estimation type for the new instance
118      * @return a new instance, with changed estimation type
119      * @throws NullArgumentException when newEstimationType is null
120      */
121     public Median withEstimationType(final EstimationType newEstimationType) {
122         return new Median(newEstimationType,
123                           percentile.getNaNStrategy(),
124                           percentile.getKthSelector());
125     }
126 
127     /**
128      * Get the {@link NaNStrategy NaN Handling} strategy used for computation.
129      * @return {@code NaN Handling} strategy set during construction
130      */
131     public NaNStrategy getNaNStrategy() {
132         return percentile.getNaNStrategy();
133     }
134 
135     /**
136      * Build a new instance similar to the current one except for the
137      * {@link NaNStrategy NaN handling} strategy.
138      *
139      * @param newNaNStrategy NaN strategy for the new instance
140      * @return a new instance, with changed NaN handling strategy
141      * @throws NullArgumentException when newNaNStrategy is null
142      */
143     public Median withNaNStrategy(final NaNStrategy newNaNStrategy) {
144         return new Median(percentile.getEstimationType(),
145                           newNaNStrategy,
146                           percentile.getKthSelector());
147     }
148 
149     /**
150      * Get the {@link KthSelector kthSelector} used for computation.
151      * @return the {@code kthSelector} set
152      */
153     public KthSelector getKthSelector() {
154         return percentile.getKthSelector();
155     }
156 
157     /**
158      * Build a new instance similar to the current one except for the
159      * {@link KthSelector kthSelector} instance specifically set.
160      *
161      * @param newKthSelector KthSelector for the new instance
162      * @return a new instance, with changed KthSelector
163      * @throws NullArgumentException when newKthSelector is null
164      */
165     public Median withKthSelector(final KthSelector newKthSelector) {
166         return new Median(percentile.getEstimationType(),
167                           percentile.getNaNStrategy(),
168                           newKthSelector);
169     }
170 
171 }