Лучшее (нелинейное) биннинг - PullRequest
2 голосов
/ 09 января 2009

Последний вопрос, который я задал, касался того, как связывать данные по x-координате. Решение было простым и элегантным, и мне стыдно, что я его не увидел. Этот вопрос может быть сложнее (или я просто слеп).

Я начал с примерно 140000 точек данных и разделил их на 70 групп, равномерно распределенных по оси X. Затем я взял среднюю позицию (x_avg, y_avg) каждой группы и нанес их на график; появилась хорошая кривая. К сожалению, есть две проблемы. Во-первых, ребра гораздо менее заселены, чем центр графика; Во-вторых, некоторые области меняются в большей степени, чем другие, и поэтому им требуется лучшее разрешение.

У меня, таким образом, есть два конкретных вопроса и общее приглашение, чтобы бросить предложения:

Имеет ли Matlab встроенный способ разбиения матрицы на фиксированное количество меньших или меньших матриц фиксированного размера?

Существует ли алгоритм (или функция matlab, но я нахожу это маловероятным) для определения границ, необходимых для более точного определения областей интереса?

В целом, есть ли лучший способ сгущения десятков тысяч точек данных в аккуратный тренд?

Ответы [ 2 ]

2 голосов
/ 09 января 2009

Звучит так, как будто вы хотите использовать ячейки, которые различаются по размеру в зависимости от плотности значений x. Я думаю, что вы все еще можете использовать функцию HISTC, как в ответе на ваш предыдущий пост, но вам просто нужно дать ему другой набор ребер.

Я не знаю, действительно ли вы этого хотите, но вот одно предложение: вместо того, чтобы разбивать ось х на 70 одинаково разнесенных групп, разбейте отсортированные данные х на 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

Это должно дать вам лотки, которые различаются по размеру в зависимости от плотности данных.


ОБНОВЛЕНИЕ: Другая версия ...

Вот еще одна идея, которая пришла мне в голову после нескольких комментариев. С помощью этого кода вы устанавливаете порог (maxDelta) для разницы между соседними точками данных в x. Любые значения x, которые отличаются от их большего соседа на величину, большую или равную maxDelta, вынуждены находиться в их собственной корзине (все они одиноки). Вы по-прежнему выбираете значение для 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 голос
/ 09 января 2009

Я никогда не использовал 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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...