# percentile
# 手动实现0
在Java中模拟Excel的PERCENTILE函数,你可以通过以下步骤实现。这涉及统计学中的百分位数计算。
# 1. 准备数据集:将数据集排序。
# 2. 计算百分位数
- 使用百分位数(如0.25表示25%)乘以数据集中数据点的数量,得到一个索引值。
- 如果这个索引值是整数,则该百分位数对应于排序后的数据集中的那个位置。
- 如果不是整数,则需要进行线性插值。
# 代码示例:
import java.util.Arrays;
public class PercentileCalculator {
public static double percentile(double[] data, double percentile) {
Arrays.sort(data);
// 索引位置
double index = percentile * (data.length - 1);
// 下标整数部分
int lowerIndex = (int) index;
// 线性插值的小数部分
double fractionalPart = index - lowerIndex;
if (lowerIndex >= data.length - 1) {
return data[lowerIndex];
} else {
// 返回线性插值结果
return data[lowerIndex] + fractionalPart * (data[lowerIndex + 1] - data[lowerIndex]);
}
}
public static void main(String[] args) {
double[] data = {3.0, 1.0, 4.0, 1.5, 2.0, 5.0, 7.0};
double p = 0.25; // 25th percentile
System.out.println("25th Percentile: " + percentile(data, p));
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 解释:
Arrays.sort(data);:先对数组进行排序。percentile * (data.length - 1):计算百分位数对应的索引值。lowerIndex是索引的整数部分。fractionalPart是索引的小数部分,用于进行线性插值。
# 结果:
对于给定的数据集,此方法将返回指定百分位数的值。
# 手动实现1
在Java中,可以通过手动实现百分位数计算来模仿Excel中的PERCENTILE函数的行为。以下是一个基本实现百分位数的示例,包括对数据排序、计算位置以及插值等步骤。
import java.util.Arrays;
public class PercentileCalculator {
// 计算百分位数
public static double percentile(double[] data, double percentile) {
// 1. 对数据进行排序
Arrays.sort(data);
int n = data.length;
// 2. 计算位置
double rank = percentile * (n - 1);
int lowerIndex = (int) Math.floor(rank);
int upperIndex = (int) Math.ceil(rank);
double fraction = rank - lowerIndex;
// 3. 插值计算
if (lowerIndex == upperIndex) {
return data[lowerIndex];
} else {
return data[lowerIndex] + fraction * (data[upperIndex] - data[lowerIndex]);
}
}
public static void main(String[] args) {
double[] data = {15, 20, 35, 40, 50};
double p = 0.4; // 40th percentile
double result = percentile(data, p);
System.out.println("Percentile: " + result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 代码详解:
排序:
Arrays.sort(data)对输入的数组进行升序排序,这是计算百分位数的基础。计算位置:
rank是按百分位数计算得到的位置。lowerIndex和upperIndex分别是计算位置的下限和上限索引。fraction是位置的小数部分,用于计算插值。
插值:
- 如果
lowerIndex和upperIndex相等,说明百分位数正好落在某个数据点上,直接返回该值。 - 如果不相等,则在两个相邻的数据点之间根据
fraction进行线性插值。
- 如果
# 例子:
在上面的代码中,计算数据集{15, 20, 35, 40, 50}的40th百分位数。经过排序和插值计算,结果将返回一个接近于这个百分位数的值。
这个实现方式与Excel中的百分位数算法类似,但可以根据需要进行调整,以匹配特定的百分位数计算标准。
# 手动实现2
这里是一个更接近Excel PERCENTILE.INC逻辑的Java实现:
import java.util.Arrays;
public class ExcelPercentile {
// 计算类似Excel中PERCENTILE.INC的百分位数
public static double percentileInc(double[] data, double percentile) {
// 1. 对数据进行排序
Arrays.sort(data);
int n = data.length;
// 2. 计算位置
double rank = (n - 1) * percentile;
int lowerIndex = (int) Math.floor(rank);
int upperIndex = (int) Math.ceil(rank);
double fraction = rank - lowerIndex;
// 3. 插值计算
if (lowerIndex == upperIndex) {
return data[lowerIndex];
} else {
return data[lowerIndex] + fraction * (data[upperIndex] - data[lowerIndex]);
}
}
public static void main(String[] args) {
double[] data = {15, 20, 35, 40, 50};
double p = 0.4; // 40th percentile
double result = percentileInc(data, p);
System.out.println("Percentile: " + result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# 例子解析:
- 假设你有一个数据集
{15, 20, 35, 40, 50},我们想计算40th百分位数。 - 首先将数据排序(已经是有序的)。
- 然后计算位置,
rank = (5 - 1) * 0.4 = 1.6,所以lowerIndex = 1(20的位置),upperIndex = 2(35的位置),并且fraction = 0.6。 - 插值结果为
20 + 0.6 * (35 - 20) = 20 + 9 = 29。
# 总结
这个Java实现更贴近于Excel中PERCENTILE.INC的计算方式,但你可能需要进一步调整,以确保它完全匹配Excel的行为。每个语言和库对百分位数的计算可能略有不同,因此在实际应用中要注意这些细节差异。
# Apache Commons Math
Apache Commons Math是一个广泛使用的数学库,提供了丰富的统计功能,包括百分位数计算。
# 安装依赖
如果使用Maven,你可以在pom.xml中添加以下依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
2
3
4
5
# 使用示例
import org.apache.commons.math3.stat.descriptive.rank.Percentile;
public class PercentileExample {
public static void main(String[] args) {
double[] data = {15, 20, 35, 40, 50};
double percentileValue = 40.0; // 40th percentile
Percentile percentile = new Percentile(percentileValue);
double result = percentile.evaluate(data);
System.out.println("Percentile: " + result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 结果
上述代码将计算并返回数组{15, 20, 35, 40, 50}的40th百分位数。
# Apache Spark(适用于大数据集)
如果你处理的是大数据集,Apache Spark中的approxQuantile方法可以高效地计算百分位数。
# 安装依赖
如果使用Maven,你可以在pom.xml中添加以下依赖:
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.12</artifactId>
<version>3.3.0</version>
</dependency>
2
3
4
5
# 使用示例
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.types.DataTypes;
public class SparkPercentileExample {
public static void main(String[] args) {
SparkSession spark = SparkSession.builder()
.appName("Percentile Example")
.master("local[*]")
.getOrCreate();
// 创建示例数据集
double[] data = {15, 20, 35, 40, 50};
Dataset<Row> df = spark.createDataFrame(
Arrays.asList(data),
DataTypes.DoubleType
).toDF("value");
// 计算百分位数
double[] percentiles = {0.4}; // 40th percentile
double[] quantiles = df.stat().approxQuantile("value", percentiles, 0.0);
System.out.println("Percentile: " + quantiles[0]);
spark.stop();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 结果
这段代码会计算数据集的近似百分位数(近似度可以通过relativeError参数调整,0.0表示精确计算)。
# Apache DataSketches
对于更复杂的数据集,尤其是流式数据,Apache DataSketches库提供了更高效的近似百分位数计算。
# 安装依赖
<dependency>
<groupId>org.apache.datasketches</groupId>
<artifactId>datasketches-java</artifactId>
<version>3.2.0</version>
</dependency>
2
3
4
5
# 使用示例
import org.apache.datasketches.quantiles.DoublesSketch;
import org.apache.datasketches.quantiles.UpdateDoublesSketch;
public class DataSketchesExample {
public static void main(String[] args) {
UpdateDoublesSketch sketch = DoublesSketch.builder().build();
double[] data = {15, 20, 35, 40, 50};
for (double value : data) {
sketch.update(value);
}
double result = sketch.getQuantile(0.4); // 40th percentile
System.out.println("Percentile: " + result);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 结果
Apache DataSketches适用于需要处理大量数据并且需要高效近似计算百分位数的场景。
# 总结
- Apache Commons Math 是最直接、方便的选择,适合一般统计计算。
- Apache Spark 适用于处理分布式大数据集。
- Apache DataSketches 则适合需要高效处理流式数据或超大数据集的应用。
每个库都提供了不同的功能和优势,具体选择可以根据应用场景来决定。