Группировка похожих значений в Matlab - PullRequest
1 голос
/ 22 июля 2011

Если у меня есть массив, содержащий значения [6712, 7023, 7510, 7509, 6718, 7514, 7509, 6247], и я хочу 4 группы схожих чисел, чтобы на выходе было 4 матрицы:

[6247]
[6712, 6718]
[7023]
[7510, 7509, 7514, 7509]

Каков наилучший способ для этого?

Ответы [ 4 ]

6 голосов
/ 22 июля 2011

Я считаю, что вы ищете термин кластеризация . Например, мы можем применить алгоритм Kmeans , чтобы сгруппировать данные в 4 кластера:

X = [6712, 7023, 7510, 7509, 6718, 7514, 7509, 6247];
[IDX,C] = kmeans(X, 4, 'EmptyAction','singleton');
G = cell(4,1);
for i=1:4
    G{i} = X(IDX==i);
end 

Это один из результатов, которые я получаю:

>> G{:}
ans =
        7510        7509        7514        7509
ans =
        7023
ans =
        6247
ans =
        6712        6718

Обычно это лучше всего работает с большим количеством точек (также работает для многомерных данных)

1 голос
/ 23 июля 2011

На самом деле, для вашего конкретного случая на самом деле нет необходимости ни в какой-либо сложной (и совершенно непонятной) процедуре кластеризации, ни в каком-либо (кажущемся простым на вид) явном решении на основе сортировки.

Если предположить, что ваши значения, близкие друг к другу (более или менее, например, abs(x- x_0)<= 50), определяют группы (представляющие интерес), тогда почему бы просто не действовать очень простым и понятным образом.

Таким образом, используя «наиболее естественную» близость ваших ценностей друг к другу;Вы можете просто сделать следующее:

>>> x= [6712 7023 7510 7509 6718 7514 7509 6247]; g= round(x/ 50)
g =
   134 140 150 150 134 150 150 125

>>> groups= {}; for g_u= unique(g), groups{end+ 1}= x(g_u== g); end
>>> groups
groups =
{
  [1,1] =  6247
  [1,2] =  6712 6718
  [1,3] =  7023
  [1,4] =  7510 7509 7514 7509
}
0 голосов
/ 22 июля 2011

Вы должны сначала решить, каковы критерии для определения границ ваших групп. Например, вы можете установить пороговое значение 50, поэтому любые значения, которые отличаются от ближайшего большего или меньшего значения, считаются находящимися в другой группе.

Вы можете решить это векторизованным способом, сначала отсортировав массив с помощью функции SORT , а затем найдя индексы в отсортированном массиве, где различия между соседними значениями превышают ваш порог (т. Е. Где границы группы) с использованием функций DIFF и FIND . Взяв различия между этими индексами (снова используя функцию DIFF ), вы получите вектор размеров для каждой группы, который можно использовать для разбиения отсортированного массива на массив ячеек с помощью функции MAT2CELL . Вот как будет выглядеть код:

threshold = 50;
array = [6712 7023 7510 7509 6718 7514 7509 6247];
sortedArray = sort(array);
nPerGroup = diff(find([1 (diff(sortedArray) > threshold) 1]));
groupArray = mat2cell(sortedArray,1,nPerGroup);

И groupArray будут массивом ячеек 1 на 4, где каждая ячейка содержит набор значений для группы. Вот содержимое groupArray для приведенного выше примера:

>> groupArray{:}

ans =

        6247

ans =

        6712        6718

ans =

        7023

ans =

        7509        7509        7510        7514
0 голосов
/ 22 июля 2011

Что вы подразумеваете под «похожим»? Например, почему 6718 не похож на 7023? Имеем ли мы в виду «разницу

Если это так, отсортируйте массив, а затем пройдитесь по нему, указав границы, где они вам нужны (т. Е. Когда разница слишком велика). Затем просто выделите новый массив.

Например ...

  GroupSimilar(values)
   1. result := list()
   2. values' := sort(values)
   3. temp := list()
   4. for i := 1 to |values'| - 1 do
   5.    if values'[i+1] - values'[i] <= diff then
   6.       temp.add(values'[i])
   7.    else
   8.        result.add(temp)
   9.        temp := list()
  10. return result
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...