插值大数据集
我有一个包含约 50 万条记录的大型数据集,代表一天中美元/英镑之间的汇率。
我有一个应用程序希望能够绘制这些数据或者可能是一个子集。出于显而易见的原因,我不想在我的图表上绘制 50 万个点。
我需要的是一个较小的数据集(100 点左右),它准确(尽可能)代表给定的数据。有谁知道可以实现这些数据的任何有趣且高效的方式?
干杯,卡尔
插值大数据集
我有一个包含约 50 万条记录的大型数据集,代表一天中美元/英镑之间的汇率。
我有一个应用程序希望能够绘制这些数据或者可能是一个子集。出于显而易见的原因,我不想在我的图表上绘制 50 万个点。
我需要的是一个较小的数据集(100 点左右),它准确(尽可能)代表给定的数据。有谁知道可以实现这些数据的任何有趣且高效的方式?
干杯,卡尔
有几种统计方法可以将大型数据集缩减为更小、更易于可视化的数据集。从您的问题中不清楚您想要什么汇总统计数据。我刚刚假设您想了解汇率如何随时间变化,但也许您对汇率超过某个值的频率或我没有考虑的其他统计数据感兴趣。
总结一段时间内的趋势
这是在R中使用lowess方法的示例(来自有关散点图平滑的文档):
> library(graphics)
# print out the first 10 rows of the cars dataset
> cars[1:10,]
speed dist
1 4 2
2 4 10
3 7 4
4 7 22
5 8 16
6 9 10
7 10 18
8 10 26
9 10 34
10 11 17
# plot the original data
> plot(cars, main = "lowess(cars)")
# fit a loess-smoothed line to the points
> lines(lowess(cars), col = 2)
# plot a finger-grained loess-smoothed line to the points
> lines(lowess(cars, f=.2), col = 3)
参数 f 控制回归与数据拟合的紧密程度。对此要考虑周到,因为您想要一些准确地适合您的数据而不会过度拟合的东西。您可以绘制汇率与时间的关系图,而不是速度和距离。
访问平滑结果也很简单。以下是如何做到这一点:
> data = lowess( cars$speed, cars$dist )
> data
$x
[1] 4 4 7 7 8 9 10 10 10 11 11 12 12 12 12 13 13 13 13 14 14 14 14 15 15 15 16 16 17 17 17 18 18 18 18 19 19
[38] 19 20 20 20 20 20 22 23 24 24 24 24 25
$y
[1] 4.965459 4.965459 13.124495 13.124495 15.858633 18.579691 21.280313 21.280313 21.280313 24.129277 24.129277
[12] 27.119549 27.119549 27.119549 27.119549 30.027276 30.027276 30.027276 30.027276 32.962506 32.962506 32.962506
[23] 32.962506 36.757728 36.757728 36.757728 40.435075 40.435075 43.463492 43.463492 43.463492 46.885479 46.885479
[34] 46.885479 46.885479 50.793152 50.793152 50.793152 56.491224 56.491224 56.491224 56.491224 56.491224 67.585824
[45] 73.079695 78.643164 78.643164 78.643164 78.643164 84.328698
您返回的数据对象包含名为 x 和 y 的条目,它们对应于传递给 lowess 函数的 x 和 y 值。在这种情况下,x 和 y 代表速度和距离。
一种想法是使用 DBMS 使用适当的查询为您压缩数据。类似于让它为特定范围取中值的东西,一个伪查询:
SELECT truncate_to_hour(rate_ts), median(rate) FROM exchange_rates
WHERE rate_ts >= start_ts AND rate_ts <= end_ts
GROUP BY truncate_to_hour(rate_ts)
ORDER BY truncate_to_hour(rate_ts)
其中 truncate_to_hour 适合您的 DBMS。或具有某种功能的类似方法将时间分割成唯一的块(例如四舍五入到最近的 5 分钟间隔),或另一个数学函数来聚合适合代替中位数的组。考虑到时间分段过程的复杂性以及 DBMS 的优化方式,在具有分段时间值的临时表上运行查询可能更有效。
如果您想自己编写,一个明显的解决方案是将您的记录集分成固定的点数块,其值将是平均值(平均值,中位数,......选择一个)。这可能具有最快的优势,并显示总体趋势。
但它缺乏价格变动的戏剧性。更好的解决方案可能包括寻找拐点,然后使用滑动窗口在拐点中进行选择。这样做的好处是可以更好地显示当天的实际事件,但速度会慢一些。
简单的方法是简单地计算对应于像素的每个时间间隔的平均值。
http://commons.wikimedia.org/wiki/File:Euro_exchange_rate_to_AUD.svg
这没有显示波动。我建议还计算每个时间间隔的标准偏差并绘制它(基本上使每个像素高于一个像素)。我找不到示例,但我知道 Gnuplot 可以做到这一点(但不是用 Java 编写的)。
如何制作枚举/迭代器包装器。我不熟悉 Java,但它可能类似于:
class MedianEnumeration implements Enumeration<Double>
{
private Enumeration<Double> frameEnum;
private int frameSize;
MedianEnumeration(Enumeration<Double> e, int len) {
frameEnum = e;
frameSize = len;
}
public boolean hasMoreElements() {
return frameEnum.hasMoreElements();
}
public Double nextElement() {
Double sum = frameEnum.nextElement();
int i;
for(i=1; (i < frameSize) && (frameEnum.hasMoreElements()); ++i) {
sum += (Double)frameEnum.nextElement();
}
return (sum / i);
}
}