Последний вопрос, который я задал, касался сортировки данных по координате x. Решение было простым и элегантным, и мне стыдно, что я его не увидел. Этот вопрос может быть сложнее (или я просто слепой).
Я начал с примерно 140000 точек данных и разделил их на 70 групп, равномерно распределенных по оси x. Затем я взял среднее положение (x_avg, y_avg) каждой группы и построил их; появился красивый изгиб. К сожалению, есть две проблемы. Во-первых, ребра заполнены гораздо меньше, чем центр графа; Во-вторых, некоторые области меняются больше, чем другие, и поэтому требуется лучшее разрешение.
Таким образом, у меня есть два конкретных вопроса и общее приглашение высказывать предложения:
Есть ли в Matlab встроенный способ разбиения матрицы на фиксированное количество меньших матриц или меньших матриц фиксированного размера?
Есть ли алгоритм (или функция Matlab, но я считаю это маловероятным) для более точного определения границ, необходимых для объединения интересующих областей?
В более общем плане, есть ли лучший способ собрать десятки тысяч точек данных в аккуратный тренд?





Я никогда не использовал 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))
k-d деревья - это бинарные деревья с добавлением плоскости разделения, прикрепленной к каждому узлу. Они также масштабируются независимо от количества имеющихся у вас размеров, поэтому вы можете просто игнорировать компонент y, отсортировать по компоненту x, и плоскости, которые вы получите, должны быть близки к оптимальным границам для ваших сегментов.
Даже если у меня есть двоичное дерево, я не понимаю, что бы я сделал для определения границ.
Похоже, вы хотите использовать ячейки, размер которых различается в зависимости от плотности значений 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
Это должно дать вам ячейки, размер которых зависит от плотности данных.
ОБНОВЛЕНИЕ: Другая версия ...
Вот еще одна идея, которую я придумал после нескольких комментариев. С помощью этого кода вы устанавливаете порог (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
Я протестировал это на нескольких небольших выборках данных, и, похоже, он работает так, как должен. Надеюсь, это сработает и для вашего набора данных, независимо от того, что он содержит! знак равно
Я обдумывал это и попробую. У меня есть две проблемы: я боюсь потерять поведение на краях, где данные не очень плотные; И все же могут быть разделы, в которых мне нужна более высокая концентрация.
Я бы попробовал приведенный выше код с кучей разных значений для nBins. Если вы сделаете nBins больше, это приведет к уменьшению размера всех ваших корзин. Это даст вам более высокую концентрацию ящиков, в которых у вас много данных. Что касается «проигрыша по краям», я не совсем понимаю, что вы имеете в виду.
Рядом с минимальным и максимальным значениями координаты x гораздо меньше точек данных. Это отодвинет среднее значение от экстремумов, и если есть интересное поведение около экстремумов, оно может быть неочевидным.
Я не думаю, что мне нужно дерево k-d; Я не сортирую по оси y. Может быть, простое двоичное дерево может работать, но я не понимаю, как это сделать.