Как накапливать наборы данных? - PullRequest
4 голосов
/ 20 января 2012

У меня есть вектор со значениями от 1 до N > 1. Некоторые значения МОГУТ появляться несколько раз подряд. Теперь я хочу иметь вторую строку, которая подсчитывает последовательно поступающие записи и удаляет все эти последовательно встречающиеся записи, например ::

A = [1 2 1 1 3 2 4 4 1 1 1 2]'

приведет к:

B = [1 1;
     2 1;
     1 2;
     3 1;
     2 1;
     4 2;
     1 3;
     2 1]

(видите, второй столбец содержит количество последовательных записей! Я недавно натолкнулся на accumarray() в MATLAB, но я не могу найти какое-либо решение для этой задачи, так как оно всегда касается всего вектора, а не только последовательных записей.

Есть идеи?

Ответы [ 2 ]

5 голосов
/ 20 января 2012

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

A = [1 2 1 1 3 2 4 4 1 1 1 2];

Сначала я собираюсь дополнить A начальным и конечным нулями, чтобы захватить первый и последний переходы

>>  A = [0, A, 0];

Места перехода можно найти там, где разница между соседними значениями не равна нулю:

>> locations = find(diff(A)~=0);

Но поскольку мы заполнили начало A нулем, первый переход не имеет смысла, поэтому мы берем только местоположения от 2: end. Значения в A из них являются значениями каждого сегмента:

>> first_column = A(locations(2:end))

ans =

     1     2     1     3     2     4     1     2

Это первый столбец - теперь нужно найти количество каждого числа. Это можно узнать по разнице в локациях. Вот где важно заполнение A на обоих концах:

>> second_column = diff(locations)

ans =

 1     1     2     1     1     2     3     1

Наконец, объединение:

B = [first_column', second_column']

B =

 1     1
 2     1
 1     2
 3     1
 2     1
 4     2
 1     3
 2     1

Все это можно объединить в одну менее читаемую строку:

>> A = [1 2 1 1 3 2 4 4 1 1 1 2]';
>> B = [A(find(diff([A; 0]) ~= 0)), diff(find(diff([0; A; 0])))]

B =

 1     1
 2     1
 1     2
 3     1
 2     1
 4     2
 1     3
 2     1
2 голосов
/ 20 января 2012

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

function B = accum_data_set(A)
    prev = A(1);
    count = 1;
    B = [];
    for i=2:length(A)
        if (prev == A(i))
            count = count + 1;
        else
            B = [B;prev count];
            count = 1;
        end
        prev = A(i);
    end
    B = [B;prev count];

выход:

>> A = [1 2 1 1 3 2 4 4 1 1 1 2]';
>> B = accum_data_set(A)

B =

     1     1
     2     1
     1     2
     3     1
     2     1
     4     2
     1     3
     2     1
...