How do I delete the intersection of sets A and B from A without sorting in MATLAB? - sorting

Two matrices, A and B:
A = [1 2 3
9 7 5
4 9 4
1 4 7]
B = [1 2 3
1 4 7]
All rows of matrix B are members of matrix A. I wish to delete the common rows of A and B from A without sorting.
I have tried setdiff() but this sorts the output.
For my particular problem (atomic coordinates in protein structures) maintaining the ordered integrity of the rows is important.

Use ISMEMBER:
%# find rows in A that are also in B
commonRows = ismember(A,B,'rows');
%# remove those rows
A(commonRows,:) = [];

I had to create diff between two arrays without sorting data. I found this great option in matlab docs. Setdiff function
Here is definition of function [C,ia] = setdiff(___,setOrder)
If you do not want output data sorted use 'stable' otherwise 'sorted' or without parameter.
Here was my use case.
yDataSent = setdiff(ScopeDataY, yDataBefore, 'stable')
yDataBefore = ScopeDataY;

Related

How to remove connected components from an image while retaining some

Let's say I have 5 connected components (labelled objects) in an image called labelledImage from bwlabel. How can I manipulate labelledImage so that the objects that are labelled as 1 and 4 only display, while removing the objects that are labelled as 2, 3 and 5. Then, how can I manipulate the original RGB image so that the connected components that are labelled as 1 and 4 only display.
I know how to retain a single connected component by using this line of code below. However, I don't know how to do this for multiple labelled regions.
Works.
connectedComponent1 = (labelledImage == 1);
imshow(connectedComponent1)
Doesn't work.
connectedComponent1and4 = (labelledImage == [1 4]);
imshow(connectedComponent1and4)
You can't do logical indexing that way. The simplest way is to perhaps use Boolean statements to combine things.
connectedCompoonent1and4 = labelledImage == 1 | labelledImage == 4;
In general, supposing you had a vector of elements that denote which components you want to keep, you could use bsxfun, permute and any to help you with that. Something like this should work:
components = [1 4];
connected = any(bsxfun(#eq, labelledImage, permute(components, [1 3 2])), 3);
The above code uses matrix broadcasting to create a temporary 3D matrix where each slice i contains the ith value of the vector components which contain the desired labels you want to keep. labelledImage is also replicated in the third dimension so the result using bsxfun creates a 3D matrix where each slice i segments out the ith object you want to keep. We then combine all of the objects together using any and looking in the third dimension.
If you don't like one-liners, you could even use a simple for loop:
components = [1 4];
connected = false(size(labelledImage, 1), size(labelledImage, 2));
for ind = 1 : numel(components)
connected = connected | labelledImage == components(ind);
end
This creates an output image that is all false, then we loop through each value in the vector of components you want to keep and append those results on top of the result. The end will give you all of the components you want to keep.
Lastly, you could use also use ismember and determine those values in your matrix that can be found between the label matrix and the components vector and simply create your mask that way:
connected = ismember(labelledImage, components);
Now that you have a mask of objects you want to extract out, to use this on the original image, simply multiply each channel with the mask. Another use of bsxfun can do that for you. Assuming your image in RGB is called img, simply do the following:
outImg = bsxfun(#times, img, cast(connected, class(img)));
To perform element-wise multiplication, you must ensure that both matrices that are being multiplied have the same type. I convert the mask into the same class as whatever the input image is and perform the multiplication.
Use ismember.
Ex:
A = randi(5,5); % your connected component matrix
B = [1 4] % list of components you want to keep
A =
4 2 1 3 5
2 4 2 5 1
3 4 5 1 4
1 4 1 3 5
4 3 5 1 5
A(~ismember(A,B)) = 0
A =
4 0 1 0 0
0 4 0 0 1
0 4 0 1 4
1 4 1 0 0
4 0 0 1 0

Append matrix to another matrix in Matlab

I have a matrix M=[4 3 2 1;1 2 3 4]. I want to append different size matrices at each iteration:
M=[4 3 2 1;1 2 3 4];
for i=1:t
newM=createNewMatrix;
M=[M;newM];
end
newM can be [] or a Nx4 matrix. This is very slow though. What is the fastest way to do this?
Update
Pre-allocating would look like this?
M=zeros(200000,4)
start=1
M(1:2,:)=M=[4 3 2 1;1 2 3 4];
for i=1:t
newM=createNewMatrix;
size_of_newM=size(newM,1);
finish=start+size_of_newM-1;
M(start:finish,:)=newM;
start=finish;
end
Like suggested, preallocation gives the most boost.
Using cell arrays is another good approach and could be implemented like this:
M = cell(200000, 1);
M{1} = [4 3 2 1; 1 2 3 4];
for t=2:200000
i = randi(3)-1;
M{t}=rand(i,4);
end
MC = vertcat(M{:});
In principle you generate a cell array with arbitrary long arrays in each cell and then concatenate them afterwards.
This worked for me nearly twice as fast as your preallocation update. On the other hand, this still was only around one second for the example with 200k iterations...

GNU Octave: How to make sure vectors in random matrix are unique?

creating an MxN matrix of random integer values in GNU Octave is very easy:
K = randi(k, M, N)
where k is the maximum value.
However, I have the requirement that each column vector in this matrix should be unique. Is there a clever way to ensure this in Octave? I could, of course, loop over all columns and calculate the pair-wise difference between all possible pairing of column vectors. But that seems a bit cumbersome.
Does anyone have a better idea?
One options would be to use unique to eliminate duplicate columns, and compare the dimensions of the result with the dimensions of the original matrix. Note that we need to transpose the matrix to be able to use the rows parameter to unique.
# Non unique columns
octave> K=[1 2 1; 2 2 2]
K =
1 2 1
2 2 2
octave> isequal(size(unique(K','rows')), size(K'))
ans = 0
# Unique columns
octave> K=[1 2 3; 2 2 2]
K =
1 2 3
2 2 2
octave> isequal(size(unique(K','rows')), size(K'))
ans = 1

fortran library for sparse matrix multiplication

I have a large matrix which I have stored in the following format, given the matrix A;
A =
1 0 3
5 1 -2
0 0 7
3 vectors;
NVPN = [1 3 4 7] - I arbitrarily put a 1 in the first column, then from the second onwards it is a cumulatively summing the number of non-zero elements per column.
NNVI = [1 2 2 1 2 3] - row index of each non-zero element.
CONT = [1 5 1 3 -2 7] - value of each non-zero element.
I now need to perform matrix*matrix multiplication and matrix*vector multiplication. Does anyone know if the are any FORTRAN libraries, which I can amend to fit my problem, to do this above?
Thanks in advance
The MATMUL function allows you to perform matrix products, which is defined in the section 13.7.70 of the FORTRAN 90 standard. See also: GCC reference.
There is already a topic on sparse matrix libraries here.

effective way of transformation from 2D to 1D vector

i want to create 1D vector in matlab from given matrix,for this i have implemented following algorithm ,which use trivial way
% create one dimensional vector from 2D matrix
function [x]=one_dimensional(b,m,n)
k=1;
for i=1:m
for t=1:n
x(k)=b(i,t);
k=k+1;
end
end
x;
end
when i run it using following example,it seems to do it's task fine
b=[2 1 3;4 2 3;1 5 4]
b =
2 1 3
4 2 3
1 5 4
>> one_dimensional(b,3,3)
ans =
2 1 3 4 2 3 1 5 4
but generally i know that,arrays are not good way to use in matlab,because it's performance,so what should be effective way for transformation matrix into row/column vector?i am just care about performance.thanks very much
You can use the (:) operator...But it works on columns not rows so you need to transpose using the 'operator before , for example:
b=b.';
b(:)'
ans=
2 1 3 4 2 3 1 5 4
and I transposed again to get a row output (otherwise it'll the same vector only in column form)
or also, this is an option (probably a slower one):
reshape(b.',1,[])

Resources