更好(非线性)分箱

时间:2009-01-09 06:14:30

标签: matlab matrix

我提出的最后一个问题涉及如何通过x坐标来分组数据。解决方案简单而优雅,我很惭愧,我没有看到它。这个问题可能更难(或者我可能只是盲目)。

我从大约140000个数据点开始,将它们分成70个沿x轴等间隔的组,然后取每个组的平均位置(x_avg,y_avg)并绘制它们;出现了一条漂亮的曲线不幸的是有两个问题。首先,边缘的填充量远小于图形的中心;其次,某些领域的变化比其他领域更多,因此需要更好的解决方案。

因此,我有两个具体问题和一般性邀请来提出建议:

matlab是否有内置的方法将矩阵拆分为固定数量的较小的matricies或固定大小的较小的matricies?

是否存在算法(或matlab函数,但我发现不太可能)来确定更精细地区分感兴趣区域所需的边界?

更一般地说,是否有更好的方法将成千上万的数据点凝聚成一个整洁的趋势?

2 个答案:

答案 0 :(得分:2)

听起来你想要根据x值的密度使用大小不一的垃圾箱。我认为您仍然可以在上一篇文章的答案中使用HISTC函数,但您只需要给它一组不同的边。

我不知道这是否是你想要的,但是这里有一个建议:不是将x轴分成70个等距组,而是将排序的x数据分成70个相等的组并确定边缘值。我认为这段代码应该有效:

% Start by assuming x and y are vectors of data:

nBins = 70;
nValues = length(x);
[xsort,index] = sort(x);  % Sort x in ascending order
ysort = y(index);         % Sort y the same way as x
binEdges = [xsort(1:ceil(nValues/nBins):nValues) xsort(nValues)+1];

% Bin the data and get the averages as in previous post (using ysort instead of y):

[h,whichBin] = histc(xsort,binEdges);

for i = 1:nBins
    flagBinMembers = (whichBin == i);
    binMembers = ysort(flagBinMembers);
    binMean(i) = mean(binMembers);
end

这应该为您提供尺寸与数据密度不同的垃圾箱。


更新:另一个版本......

这是我在发表一些评论后提出的另一个想法。使用此代码,您可以为x中的相邻数据点之间的差异设置阈值(maxDelta)。任何与其较大邻居相差大于或等于maxDelta的x值都被强制放在他们自己的bin中(所有这些都是他们的寂寞)。您仍然为nBins选择一个值,但当展开点降级到自己的箱子时,最终的箱数将大于此值。

% Start by assuming x and y are vectors of data:

maxDelta = 10; % Or whatever suits your data set!
nBins = 70;
nValues = length(x);
[xsort,index] = sort(x);  % Sort x in ascending order
ysort = y(index);         % Sort y the same way as x

% Create bin edges:

edgeIndex = false(1,nValues);
edgeIndex(1:ceil(nValues/nBins):nValues) = true;
edgeIndex = edgeIndex | ([0 diff(xsort)] >= maxDelta);
nBins = sum(edgeIndex);
binEdges = [xsort(edgeIndex) xsort(nValues)+1];

% Bin the data and get the y averages:

[h,whichBin] = histc(xsort,binEdges);

for i = 1:nBins
    flagBinMembers = (whichBin == i);
    binMembers = ysort(flagBinMembers);
    binMean(i) = mean(binMembers);
end

我在几个小样本数据集上测试了它,它似乎做了它应该做的事情。希望它也适用于您的数据集,无论它包含什么! =)

答案 1 :(得分:1)

我从来没有使用过matlab,但是从查看你之前的问题开始,我怀疑你是在寻找Kdtree或变体的内容。

澄清:由于似乎有一些混淆,我认为伪代码示例是有序的。

// Some of this shamelessly borrowed from the wikipedia article
function kdtree(points, lower_bound, upper_bound) {
    // lower_bound and upper_bound are the boundaries of your bucket
    if(points is empty) {
        return nil
    }
    // It's a trivial exercise to control the minimum size of a partition as well
    else {
        // Sort the points list and choose the median element
        select median from points.x

        node.location = median;

        node.left = kdtree(select from points where lower_bound < points.x <= median, lower_bound, median);
        node.right = kdtree(select from points where median < points.x <= upper_bound, median, upper_bound);

        return node
    }
}

kdtree(points, -inf, inf)

// or alternatively

kdtree(points, min(points.x), max(points.x))