即时插入大型数据集

时间:2010-03-25 11:11:27

标签: java collections interpolation

插值大数据集

我有大约0.5百万条记录的大数据,代表了某一天美元/英镑之间的汇率。

我有一个应用程序,希望能够绘制此数据或可能是子集。出于显而易见的原因,我不想在我的图表上绘制50万点。

我需要的是一个较小的数据集(100点左右),它准确(尽可能)代表给定的数据。有谁知道这些数据可以实现的任何有趣和高效的方式?

干杯,卡尔

6 个答案:

答案 0 :(得分:4)

有几种统计方法可以将大型数据集缩减为更小,更易于可视化的数据集。从您的问题中不清楚您想要什么汇总统计。我只是假设你想看看汇率如何随着时间的变化而变化,但也许你对汇率超过某个值的频率或者我没有考虑的其他统计数据感兴趣。

总结一段时间内的趋势

以下是lowess中使用R方法的示例(来自scatter plot smoothing上的文档):

> 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代表速度和dist。

答案 1 :(得分:3)

一种想法是使用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如何优化,在具有分段时间值的临时表上运行查询可能更有效。

答案 2 :(得分:1)

RRDTool之类的内容会自动执行您的操作 - tutorial可以帮助您入门,drraw会为数据绘制图形。

我在工作中使用它来处理错误图表这样的事情,我不需要在6个月的时间内解析1分钟,仅限最近的几个小时。之后我有1小时的分辨率,然后是1天的分辨率,持续几个月。

答案 3 :(得分:1)

如果您想编写自己的,一个明显的解决方案是将您的记录集分成固定的点数块,其值将是平均值(平均值,中值,...选择一个)。这有可能是最快的优势,并显示整体趋势。

但它缺乏价格上涨的戏剧性。更好的解决方案可能包括寻找拐点,然后使用滑动窗口在其中进行选择。这样做的好处是可以更好地显示当天的实际事件,但速度会慢一些。

答案 4 :(得分:1)

朴素的方法是简单地计算对应于像素的每个时间间隔的平均值。

http://commons.wikimedia.org/wiki/File:Euro_exchange_rate_to_AUD.svg

这并未显示出波动。我建议还计算每个时间间隔的标准偏差并绘制它(基本上使每个像素高于一个像素)。我找不到一个例子,但我知道Gnuplot可以做到这一点(但不是用Java编写的)。

答案 5 :(得分:0)

如何制作枚举/迭代器包装器。我不熟悉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);
    }
}