mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[apps/stats] Fix median computation
This commit is contained in:
@@ -178,17 +178,7 @@ double Store::quartileRange(int series) const {
|
||||
}
|
||||
|
||||
double Store::median(int series) const {
|
||||
bool exactElement = true;
|
||||
double minMedian = sortedElementAtCumulatedFrequency(series, 1.0/2.0, &exactElement);
|
||||
if (!exactElement) {
|
||||
double maxMedian = sortedElementAfter(series, minMedian);
|
||||
if (maxMedian == DBL_MAX) {
|
||||
return minMedian;
|
||||
}
|
||||
return (minMedian + maxMedian)/2.0;
|
||||
} else {
|
||||
return minMedian;
|
||||
}
|
||||
return sortedElementAtCumulatedFrequency(series, 1.0/2.0, true);
|
||||
}
|
||||
|
||||
double Store::sum(int series) const {
|
||||
@@ -251,7 +241,7 @@ double Store::sumOfValuesBetween(int series, double x1, double x2) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
double Store::sortedElementAtCumulatedFrequency(int series, double k, bool * exactElement) const {
|
||||
double Store::sortedElementAtCumulatedFrequency(int series, double k, bool createMiddleElement) const {
|
||||
// TODO: use an other algorithm (ex quickselect) to avoid quadratic complexity
|
||||
assert(k >= 0.0 && k <= 1.0);
|
||||
double totalNumberOfElements = sumOfOccurrences(series);
|
||||
@@ -263,25 +253,16 @@ double Store::sortedElementAtCumulatedFrequency(int series, double k, bool * exa
|
||||
sortedElementIndex = minIndex(bufferValues, numberOfPairsOfSeries(series));
|
||||
bufferValues[sortedElementIndex] = DBL_MAX;
|
||||
cumulatedFrequency += m_data[series][1][sortedElementIndex] / totalNumberOfElements;
|
||||
if (exactElement != nullptr && cumulatedFrequency == k) {
|
||||
*exactElement = false;
|
||||
}
|
||||
if (createMiddleElement && cumulatedFrequency == k) {
|
||||
int nextElementIndex = minIndex(bufferValues, numberOfPairsOfSeries(series));
|
||||
if (bufferValues[nextElementIndex] != DBL_MAX) {
|
||||
return (m_data[series][0][sortedElementIndex] + m_data[series][0][nextElementIndex]) / 2.0;
|
||||
}
|
||||
}
|
||||
return m_data[series][0][sortedElementIndex];
|
||||
}
|
||||
|
||||
double Store::sortedElementAfter(int series, double k) const {
|
||||
assert(numberOfPairsOfSeries(series) > 0);
|
||||
double result = DBL_MAX;
|
||||
for (int i = 0; i < numberOfPairsOfSeries(series); i++) {
|
||||
double currentElement = m_data[series][0][i];
|
||||
if (currentElement > k && currentElement < result) {
|
||||
result = currentElement;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int Store::minIndex(double * bufferValues, int bufferLength) const {
|
||||
int index = 0;
|
||||
for (int i = 1; i < bufferLength; i++) {
|
||||
|
||||
@@ -59,8 +59,7 @@ public:
|
||||
private:
|
||||
double defaultValue(int series, int i, int j) const override;
|
||||
double sumOfValuesBetween(int series, double x1, double x2) const;
|
||||
double sortedElementAtCumulatedFrequency(int series, double k, bool * exactElement = nullptr) const;
|
||||
double sortedElementAfter(int series, double k) const;
|
||||
double sortedElementAtCumulatedFrequency(int series, double k, bool createMiddleElement = false) const;
|
||||
int minIndex(double * bufferValues, int bufferLength) const;
|
||||
// Histogram bars
|
||||
double m_barWidth;
|
||||
|
||||
Reference in New Issue
Block a user