Вопрос
Последний вопрос, который я задал, касался того, как связывать данные по x-координате. Решение было простым и элегантным, и мне стыдно, что я его не увидел. Этот вопрос может быть сложнее (или я просто слеп).
Я начал с примерно 140000 точек данных и разделил их на 70 групп, равномерно распределенных по оси X. Затем я взял среднюю позицию (x_avg, y_avg) каждой группы и нанес их на график; появилась хорошая кривая. К сожалению, есть две проблемы. Во-первых, ребра гораздо менее заселены, чем центр графика; Во-вторых, некоторые области меняются больше, чем другие, и поэтому нуждаются в лучшем разрешении.
У меня, таким образом, есть два конкретных вопроса и общее приглашение, чтобы бросить предложения:
Есть ли в Matlab встроенный способ разбиения матрицы на фиксированное число меньших или меньших матриц фиксированного размера?
Существует ли алгоритм (или функция matlab, но я нахожу это маловероятным) для определения границ, необходимых для более точного определения областей интереса?
В целом, есть ли лучший способ сконденсировать десятки тысяч точек данных в аккуратный тренд?
Решение
Звучит так, как будто вы хотите использовать ячейки, размер которых зависит от плотности значений 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
Я проверил это на нескольких небольших выборочных наборах данных, и он, кажется, делает то, что должен. Надеюсь, это будет работать и для вашего набора данных, что бы он ни содержал! =) Р>
Другие советы
Я никогда не использовал 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))