MATLAB: Starting with a vector of starting points and a vector of end points, make runs of consecutive numbers between these points [duplicate] - matlab

This question already has answers here:
Vectorizing the Notion of Colon (:) - values between two vectors in MATLAB
(4 answers)
Closed 9 years ago.
This is probably simple but here is my problem.
I have two vectors, starts and ends. Starts are the starting points of sequences of consecutive numbers and ends are the end points of sequences of consecutive numbers. I would like to create a vector which contains these runs.
So for example, say
starts = [2 7 10 18 24]
ends = [5 8 15 20 30]
I would like to create the following vector
ans = [2 3 4 5 7 8 10 11 12 13 14 15 18 19 20 24 25 26 27 28 29 30]
Using starts:end only uses the first element of each vector
I would also like to do this without using a (for) loop in order to keep it as fast as possible!
Thanks for reading
Chris

Assuming there's always the same number of start and end points, and they always match (e.g. the nth start corresponds to the nth end), then you can do
cell2mat(arrayfun(#(s,e) (s:e), starts, ends, 'UniformOutput', false))
For a bit more detailed explanation, the arrayfun(#(s,e) (s:e), starts, ends, 'UniformOutput', false) part will generate a sequence of n cell arrays, where n is the length of the starts and ends vectors, such that each cell array has the sequence starts(i):ends(i) corresponding to the ith elements of the two vectors. Then the cell2mat function will fuse each of the individual cell arrays into 1 larger matrix.

When you're worried about making it fast, preallocate:
starts = [2 7 10 18 24]
ends = [5 8 15 20 30]
a = zeros(1,sum(ends)+numel(ends)-sum(starts));
% or a = zeros(1,sum(ends+1-starts))
j = 1;
for i = 1:numel(ends)
j2 = j+ends(i)-starts(i);
a(j:j2) = (starts(i):ends(i));
j = j2+1;
end

Related

What the meaning of this index in MATLAB?

data = reshape(1:21504,[256,4,21]);
data(:,5:4:end)
I test some indexes, such as:
data(:,5:4:end) ~= data(:,5:4:end,1)
data(:,5:4:end) ~= data(:,1,5:4:end)
So what is the meaning of data(:,5:4:end)?
I test some other indexes, such as:
data(1,1) == data(1,1,1)
data(1,1:3) == data(1,1:3,1)
And find some strange behavior ,such as data(1,1:10,1) returns error but data(1,1:10) is ok.
So What's happening here?
How can I understand this mechanism?
>> size(data)
ans =
256 4 21
data(1,1:10,1) selects column 1-10 from first row (all three dimensions are explicitly set), but there are only 4 columns. Therefore the error.
data(1,1:10), on the other hand, uses Linear indexing, which interpretes dimensions 2 and 3 as one long strung of values and selects its first 10 values.
Linear Indexing
What does this expression A(14) do?
When you index into the matrix A using only one subscript, MATLAB treats A as if its elements were strung out in a long column vector, by going down the columns consecutively, as in:
16
5
9
...
8
12
1
The expression A(14) simply extracts the 14th element of the implicit column vector. Indexing into a matrix with a single subscript in this way is often called linear indexing.
Here are the elements of the matrix A along with their linear indices:
matrix_with_linear_indices.gif
The linear index of each element is shown in the upper left.
From the diagram you can see that A(14) is the same as A(2,4).
The single subscript can be a vector containing more than one linear index, as in:
A([6 12 15])
ans =
11 15 12
Consider again the problem of extracting just the (2,1), (3,2), and (4,4) elements of A. You can use linear indexing to extract those elements:
A([2 7 16])
ans =
5 7 1
That's easy to see for this example, but how do you compute linear indices in general? MATLAB provides a function called sub2ind that converts from row and column subscripts to linear indices. You can use it to extract the desired elements this way:
idx = sub2ind(size(A), [2 3 4], [1 2 4])
ans =
2 7 16
A(idx)
ans =
5 7 1
(Copied from http://de.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html)
data(:, 5:4:end) will access all elements in the first dimension of data and starting from index 5 every 4th index until the last index in the second dimension of data. The syntax for this indexing technique can be explained like this:
data(startIndex:step:endIndex)
If data has more dimensions than you used for indexing, this will assume : for every dimension after that.
To sum up my question:
data=reshape(1:24,2,3,4)
data(:,:,1) =
1 3 5
2 4 6
data(:,:,2) =
7 9 11
8 10 12
data(:,:,3) =
13 15 17
14 16 18
data(:,:,4) =
19 21 23
20 22 24
Using this example you can know what Matlab doing:
data(:,1)
ans =
1
2
data(:,12)
ans =
23
24
data(:,[1,12])
ans =
1 23
2 24
data(:,5:4:end)
ans =
9 17
10 18
If you use data(:,13),it throws an error.

How to generate a matrix containing all permutations (without repetition) of an array? [duplicate]

This question already has answers here:
Generate a matrix containing all combinations of elements taken from n vectors
(4 answers)
Closed 6 years ago.
Can anyone please help in writing the code to generate a matrix of which each row should contain a new arrangement (permutation without repetition)?
I have tried the following:
%Generate an array of 8 elements randomly
array=floor(randi([0,100],1,K));
%Generate all permutations of 'array'. Each row signifies a new arrangement
%all_matrix=perms(array);
%// Create all possible permutations (with repetition) of letters stored in x
C = cell(K, 1); %// Preallocate a cell array
[C{:}] = ndgrid(array); %// Create K grids of values
y = cellfun(#(array){array(:)}, C); %// Convert grids to column vectors
all_matrix_repetition = [y{:}];
all_matrix=zeros(factorial(K),K);
for i=1:size(all_matrix_repetition,1)
if length(all_matrix_repetition(i,:))==length(unique(all_matrix_repetition(i,:)))
all_matrix(count,:)=all_matrix_repetition(i,:);
count=count+1;
end
end
But getting the memory error. I am using Matlab 2011a. Please help me.
If I understood right I think this will do:
arraySize = 3;
array = randi(100,[1 arraySize]);
indexes = perms(1:arraySize);
permutated = array(indexes);
Where you would get, for instance:
array =
19 24 42
indexes =
3 2 1
3 1 2
2 3 1
2 1 3
1 2 3
1 3 2
permutated =
42 24 19
42 19 24
24 42 19
24 19 42
19 24 42
19 42 24

how to extract the numbers above and below the diagonal of a matrix into two separate vectors in matlab [duplicate]

This question already has answers here:
how to find upper and lower diagonal matrix matlab
(2 answers)
Closed 8 years ago.
I am new to matlab. I have large N X N matrix and i need to extract the numbers above the diagonal in a vector and the same with the numbers below the diagonal, but into a separate vector.
Use diag which extracts numbers in a matrix along a diagonal. The default behaviour is to extract the values over the main diagonal of a matrix (i.e. the row and column numbers are the same), but you can specify an additional parameter that specifies an offset of whether you want to sample above or below the main diagonal.
As such, if you want to go one above the diagonal, you'd specify the second parameter as 1. To go below, you'd specify the second parameter as -1.
Let's show an example with a 5 x 5 matrix A, like so:
A = reshape(1:25, 5, 5)
A =
1 6 11 16 21
2 7 12 17 22
3 8 13 18 23
4 9 14 19 24
5 10 15 20 25
To get the diagonal right above the main diagonal, you would do:
vec1 = diag(A,1)
Our output is:
vec1 =
6
12
18
24
Similarly, to get the diagonal right below the main diagonal, you would do:
vec2 = diag(A,-1)
Our output is:
vec2 =
2
8
14
20

how to find the middle elements of sub matrices in a matrix

I have a matrix and i want to consider it has 4 sub matrices which are placed together. How can I find the middle element of each sub matrix when they are together?
consider the matrix below. It is built by 4 sub matrices.
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
31 32 33 34 35 36
I want to get their middle elements so i could have:
8, 11, 26, 29
From what I have understood this might work for you and this is a demo, so use your own parameters -
Code
%%// Input matrix
A = rand(44,44);
%%/ Number of submatrices needed
num_submat = 16;%%// 4 for your example case
%%/ Number of submatrices along row and column
num_submat1= sqrt(num_submat);
%%// Middle element indices along each direction
v1 = floor(size(A,2)/(2*num_submat1))+1:size(A,2)/(num_submat1):size(A,2);
%%// Middle elements
middle_ele = A(v1,v1)
It is always helpful to know that matrix indexing in matlab goes columnwise eg,
indOrd = [1,4,7;2,5,8;3,6,9]
where the number is the index order and not related to your example. indOrd(4) would return 4. Try to use this to find the index locations.
Assuming that each submatrix has odd size 2n+1, the coordinates of the center of one submatrix alone are [n+1, n+1]. If your have a square with M*M submatrices (M=2 in your case), the coordinates are [n+1+i*(2*n+1), n+1+j*(2*n+1)], i and j taken independently in the range 0:M-1.
Turning back to Matlab, it is now quite easy to generate all indices of the centers of the submatrices grouped in the matrix A:
n = floor(size(A,1)/(2*M));
xc = n+1+reshape(repmat(0:M-1,M,1),[],1);
yc = n+1+reshape(repmat((0:M-1)',1,M),[],1);
centers = A(yc, xc);
For even-sized submatrix, you have to choose which element is the center, the modification is quite easy to do then.

Removing a row in a matrix, by removing an entry from a possibly different row for each column

I have a vector of values which represent an index of a row to be removed in some matrix M (an image). There's only one row value per column in this vector (i.e. if the image is 128 x 500, my vector contains 500 values).
I'm pretty new to MATLAB so I'm unsure if there's a more efficient way of removing a single pixel (row,col value) from a matrix so I've come here to ask that.
I was thinking of making a new matrix with one less row, looping through each column up until I find the row whose value I wish to remove, and "shift" the column up by one and then move onto the next column to do the same.
Is there a better way?
Thanks
Yes, there is a solution which avoids loops and is thus faster to write and to execute. It makes use of linear indexing, and exploits the fact that you can remove a matrix entry by assigning it an empty value ([]):
% Example data matrix:
M = [1 5 9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20];
% Example vector of rows to be removed for each column:
vector = [2 3 4 1 3];
[r c] = size(M);
ind = sub2ind([r c],vector,1:c);
M(ind) = [];
M = reshape(M,r-1,c);
This gives the result:
>> M =
1 5 9 14 17
3 6 10 15 18
4 8 11 16 20