Remove single elements from a vector

I have a vector M containing single elements and repeats. I want to remove all individual items. Turning something like [1 1 2 3 4 5 4 4 5]

in [1 1 4 5 4 4 5]

.

I thought I would try to get the count of each item and then use the index to remove what I don't need, something like this:

uniq = unique(M);
list = [uniq histc(M,uniq)];

      

Though I'm stuck here and not sure how to go forward. Can anyone please help?

+3


source to share


4 answers


You can get the result with the following code:

A = [a.', ones(length(a),1)];
[C,~,ic] = unique(A(:,1));
result = [C, accumarray(ic,A(:,2))];
a = A(~ismember(A(:,1),result(result(:,2) == 1))).';

      



The idea is to add to the second column a'

, then the accumarray

base in the first column (items a

). After that, the items in the first column are found that add up the sum in the second column. Therefore, these elements are repeated once per a

. Finally, removing them from the first column a

.

+1


source


Here is a solution using , and unique

histcounts

ismember

tmp=unique(M) ;            %finding unique elements of M
%Now keeping only those elements in tmp which appear only once in M
tmp = tmp(histcounts(M,[tmp tmp(end)])==1); %Thanks to rahnema for his insight on this 
[~,ind] = ismember(tmp,M); %finding the indexes of these elements in M
M(ind)=[];

      




histcounts

was introduced in R2014b. For earlier versions can be used by replacing this line with the following: hist

tmp=tmp(hist(M,tmp)==1);

      

+2


source


Here's a cheaper alternative:

[s ii] = sort(a);
x = [false s(2:end)==s(1:end-1)]
y = [x(2:end)|x(1:end-1) x(end)]
z(ii) = y;
result = a(z);

      

Assuming the input

a =

1   1   8   8   3   1   4   5   4   6   4   5

      

sort the list s

and get the index of the sorted listii

s= 

1   1   1   3   4   4   4   5   5   6   8   8

      

we can find the index of the repeated elements and for that we check if the element is equal to the previous element

x =

0   1   1   0   0   1   1   0   1   0   0   1

      

however, in the x

first elements of each block are omitted, to find it, we can apply [or]

between each element with the previous element

 y = 

1   1   1   0   1   1   1   1   1   0   1   1

      

now we have sorted the boolean index of the repeating elements. It should be reordered in its original order. For this we use the index of the sorted items ii

:

z =

1   1   1   1   0   1   1   1   1   0   1   1

      

finally, use z to extract only duplicate items.

result = 

1   1   8   8   1   4   5   4   4   5

      

Here is the test result in Octave * for the following input:

a = randi([1 100000],1,10000000);

-------HIST--------
Elapsed time is 5.38654 seconds.
----ACCUMARRAY------
Elapsed time is 2.62602 seconds.
-------SORT--------
Elapsed time is 1.83391 seconds.
-------LOOP--------
Doesn't complete in 15  seconds.

      

* Since it histcounts

was not implemented in Octave , so instead histcounts

I used hist

.

You can test it online

+1


source


X = [1 1 2 3 4 5 4 4 5];
Y = X;
A = unique(X);
for i = 1:length(A)
    idx = find(X==A(i));
    if length(idx) == 1
        Y(idx) = NaN;
    end
end
Y(isnan(Y)) = [];   

      

Then it Y

will be [1 1 4 5 4 4 5]

. It detects all the individual elements and makes them like NaN

and then removes all the elements NaN

from the vector.

0


source







All Articles