在 Java 中計算百分位數
1. 概述
在 Java 中分析資料時,計算百分位數是理解數值資料集的統計分佈和特徵的基本任務。
在本教程中,我們將逐步介紹用 Java 計算百分位數的過程,並提供程式碼範例和解釋。
2. 理解百分位數
在討論實作細節之前,我們先了解什麼是百分位數以及它們在資料分析中的常用用法。
百分位數是統計中使用的一種測量,指示給定的觀察百分比處於或低於該值的值。例如,第 50 個百分位數(也稱為中位數)表示 50% 的資料點低於該值。
值得注意的是,百分位數以與輸入資料集相同的測量單位表示,而不是百分比。例如,如果資料集涉及月薪,則相應的百分位將以美元、歐元或其他貨幣表示。
接下來,讓我們來看幾個具體的例子:
Input: A dataset with numbers 1-100 unsorted
-> sorted dataset: [1, 2, ... 49, (50), 51, 52, ..100]
-> The 50th percentile: 50
Input: [-1, 200, 30, 42, -5, 7, 8, 92]
-> sorted dataset: [-2, -1, 7, (8), 30, 42, 92, 200]
-> The 50th percentile: 8
百分位數通常用於了解資料分佈、識別異常值以及比較不同的資料集。在處理大型資料集或簡潔總結資料集的特徵時,它們特別有用。
接下來,讓我們看看如何在Java中計算百分位數。
3. 計算Collection
的百分位數
現在我們了解了百分位數是什麼。讓我們總結一下實作百分位計算的逐步指南:
- 按升序對給定資料集進行排序
- 計算所需百分位的排名為
(percentile / 100) * dataset.size
- 取排名的上限,因為排名可以是小數
- 最終結果是排序資料集中索引
ceiling(rank) – 1
元素
接下來,我們建立一個通用方法來實作上述邏輯:
static <T extends Comparable<T>> T getPercentile(Collection<T> input, double percentile) {
if (input == null || input.isEmpty()) {
throw new IllegalArgumentException("The input dataset cannot be null or empty.");
}
if (percentile < 0 || percentile > 100) {
throw new IllegalArgumentException("Percentile must be between 0 and 100 inclusive.");
}
List<T> sortedList = input.stream()
.sorted()
.collect(Collectors.toList());
int rank = percentile == 0 ? 1 : (int) Math.ceil(percentile / 100.0 * input.size());
return sortedList.get(rank - 1);
}
正如我們所看到的,上面的實作非常簡單。然而,值得一提的是:
- 需要驗證
percentile
參數(0<= percentile <= 100
) - 我們使用 Stream API 對輸入資料集進行排序,並將排序結果收集到新清單中,以避免修改原始資料集
接下來,讓我們測試getPercentile()
方法。
4. 測試getPercentile()
方法
首先,如果百分位數超出有效範圍,則該方法應拋出IllegalArgumentException
:
assertThrows(IllegalArgumentException.class, () -> getPercentile(List.of(1, 2, 3), -1));
assertThrows(IllegalArgumentException.class, () -> getPercentile(List.of(1, 2, 3), 101));
我們使用**assertThrows()
方法來驗證是否引發了預期的異常**。
接下來,我們以 1-100 的List
作為輸入來驗證方法是否能夠產生預期的結果:
List<Integer> list100 = IntStream.rangeClosed(1, 100)
.boxed()
.collect(Collectors.toList());
Collections.shuffle(list100);
assertEquals(1, getPercentile(list100, 0));
assertEquals(10, getPercentile(list100, 10));
assertEquals(25, getPercentile(list100, 25));
assertEquals(50, getPercentile(list100, 50));
assertEquals(76, getPercentile(list100, 75.3));
assertEquals(100, getPercentile(list100, 100));
在上面的程式碼中,我們透過IntStream
準備輸入清單。此外,我們使用shuffle()
方法對100 個數字進行隨機排序。
此外,讓我們使用另一個資料集輸入來測試我們的方法:
List<Integer> list8 = IntStream.of(-1, 200, 30, 42, -5, 7, 8, 92)
.boxed()
.collect(Collectors.toList());
assertEquals(-5, getPercentile(list8, 0));
assertEquals(-5, getPercentile(list8, 10));
assertEquals(-1, getPercentile(list8, 25));
assertEquals(8, getPercentile(list8, 50));
assertEquals(92, getPercentile(list8, 75.3));
assertEquals(200, getPercentile(list8, 100));
5. 從陣列計算百分位數
有時,給定的資料集輸入是數組而不是Collection
。在這種情況下,我們可以先將輸入數組轉換為List
,然後利用getPercentile()
方法來計算所需的百分位數。
接下來,讓我們示範如何透過將long
數組作為輸入來實現這一點:
long[] theArray = new long[] { -1, 200, 30, 42, -5, 7, 8, 92 };
//convert the long[] array to a List<Long>
List<Long> list8 = Arrays.stream(theArray)
.boxed()
.toList();
assertEquals(-5, getPercentile(list8, 0));
assertEquals(-5, getPercentile(list8, 10));
assertEquals(-1, getPercentile(list8, 25));
assertEquals(8, getPercentile(list8, 50));
assertEquals(92, getPercentile(list8, 75.3));
assertEquals(200, getPercentile(list8, 100));
如程式碼所示,**由於我們的輸入是基元數組 ( long[]
),因此我們使用Arrays.stream()
將其轉換為List<Long>
.
**然後,我們可以將轉換後的List
傳遞給getPercentile()
以獲得預期結果。
六,結論
在本文中,我們首先討論了百分位數的基本原則。然後,我們探討如何用 Java 計算資料集的百分位數。
與往常一樣,範例的完整原始程式碼可 在 GitHub 上取得。