Java 线性插值填充缺失点
Posted smile-yan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java 线性插值填充缺失点相关的知识,希望对你有一定的参考价值。
问题描述
已知时间戳与对应的值,需要根据时间戳找到缺失的点,然后进行值的填充。
例如:
timestamp | value |
---|---|
1 | 1.0 |
2 | 2.0 |
/ | / |
4 | 4.0 |
5 | 5.0 |
/ | / |
/ | / |
8 | 8.0 |
9 | 9.0 |
填充其中三个缺失的地方分别:
timestamp | value |
---|---|
/ | 3.0 |
/ | 6.0 |
/ | 7.0 |
源码
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
引入相应的依赖包
import java.util.LinkedList;
import java.util.List;
import org.apache.commons.math3.analysis.interpolation.LinearInterpolator;
import org.apache.commons.math3.analysis.polynomials.PolynomialSplineFunction;
缺失值填充的源码:
/**
* 根据时间戳进行填充value
* @param timestamps 时间戳数组
* @param values 对应的值
* @param interval 时间戳
* @return 填充后的list
*/
public static List<Double> insertMissingByTimestamps(List<Long> timestamps,
List<Double> values,
Long interval) {
// 检查问题
if (timestamps == null || values == null ||
timestamps.size() == 0 || values.size() == 0) {
return null;
}
// 准备好线性插值
LinearInterpolator interp = new LinearInterpolator();
double[] timestampsAry = timestamps.stream().mapToDouble(d -> d).toArray();
double[] valuesAry = values.stream().mapToDouble(d -> d).toArray();
PolynomialSplineFunction insertMissingFunc = interp.interpolate(timestampsAry, valuesAry);
// 计算正常情况下有多少个点
final int normalSize = countMissingPoints(timestamps, interval);
long current = timestamps.get(0);
List<Double> target = new LinkedList<>();
// 填充
for (int i=0; i<timestamps.size() && target.size() < normalSize; ) {
// 如果存在,则添加
if (current == timestamps.get(i)) {
target.add(values.get(i));
i++;
} else {
// 如果不存在,则插值
double value = insertMissingFunc.value(current);
target.add(value);
}
current += interval;
}
return target;
}
测试用例
double[] x = { 1, 3, 4, 7, 8, 9, 10};
double[] y = { 1, 3, 4, 7, 8, 9, 10};
LinearInterpolator interp = new LinearInterpolator();
PolynomialSplineFunction f = interp.interpolate(x, y);
System.out.println("Piecewise functions:");
Arrays.stream(f.getPolynomials()).forEach(System.out::println);
double value = f.value(5);
double value2 = f.value(6);
System.out.println("x = 3, y = " + f.value(3));
System.out.println("x = 6, y = " + f.value(6));
System.out.println("x = 7, y = " + f.value(7));
测试输出内容:
1 + x
2 + x
4 + x
5 + x
8 + x
x = 3, y = 3.0
x = 6, y = 6.0
x = 7, y = 7.0
注意:如果是边界外的是不能计算的。比如这个题目中不能计算 f.value(10)
。
总结
很简单的东西,但是找了很久才找到这个库文件以及使用例子。总结一下,希望能够帮到需要的小伙伴们。
Smileyan
2021.11.5 17:30
以上是关于Java 线性插值填充缺失点的主要内容,如果未能解决你的问题,请参考以下文章
R语言ggplot2可视化:使用pracma包的interp1函数对缺失值进行线性插值后进行可视化分析用虚线标记进行数据填充的区域