Variable-Length Array Addressing in Matlab - matlab

I'm sure there's an easy answer to this, but I'm not really sure what to search for. I have an array, M, of D dimensions, where D is constrained to be 1 <= D <= 5, and a vector of length D, X. I'd like to use D as an address within M and increment the value at that address, so if D were [1 2 3], I would want to increment M(1,2,3). I know I can do it like so:
if D == 1
M(X(1)) = M(X(1)) + 1;
end
if D == 2
M(X(1), X(2)) = M(X(1), X(2)) + 1;
end
But it's really ugly and I have to imagine there's a simpler, less clumsy way. Thanks!

You can use the function sub2ind to convert the address vector D to the corresponding dimensions in M. However, this would require that you store D as a cell and not a vector. The following example should help.
A=magic(5);%# just a test matrix
A=
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
d={3,4};%we need the element at row 3, column 4
indx=sub2ind(size(A),d{:});%# get the index corresponding to the subscript 3,4
A(indx)
ans=
20
You can also directly index it into the matrix A as A(sub2ind(size(A),d{:})), without having to create a separate variable.
You can also use num2cell to convert the vector to a cell. This might be a better option, as you might want to store D as a vector for other purposes. So the corresponding line becomes
indx=sub2ind(size(A),num2cell(d));

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 assign part of a matrix to other matrix in matlab

I have a 30 x 30 matrix, called A, and I want to assign B as the leftmost 30 x 20 block of A how can I do that?
Is this the correct way to do it?
B = A[30 ; 20]
No the correct way is
B = A(:, 1:20);
where : is shorthand for all of the rows in A.
Matrix indexing in MATLAB uses round brackets, (). Square brackets, [], are used to declare matrices (or vectors) as in
>> v = [1 2 3; 4 5 6; 7 8 9]
v =
1 2 3
4 5 6
7 8 9
excaza provides a very good link on Matrix Indexing in MATLAB which should help you. There is also Matrix Indexing.
A_new = A(:,1:20)
takes all the rows from A with this part A(:,) and the first 20 columns with this part A(,1:20)
A_newis now 30x20
You can also iterate over elements in two loops, but the above answer is easiest

Matlab, Sum Function for a Matrix row

Basically the sum function calculate the sum of the columns, that is to say if we have a 4x4 matrix we would get a 1X4 vector
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A)
ans =
34 34 34 34
But if I want to get the Summation of the rows then i have 2 methods, the first is to get the transpose of the matrix then get the summation of the transposed matrix,and finally get the transpose of the result...., The Second method is to use dimension argument for the Sum function "sum(A, 2)"
A = magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
sum(A,2)
ans =
34
34
34
34
The problem is here I cannot understand how this is done, If anyone could please tell me the idea/concept behind this method,
It's hard to tell exactly how sum internally works, but we can guess it does something similar to this.
Matlab stores matrices (or N-dimensional arrays) in memory using column-major order. This means the order for the elements in memory for a 3 x 4 matrix is
1 4 7 10
2 5 8 11
3 6 9 12
So it first stores element (1,1), then (1,2), then (13), then (2,1), ...
In fact, this is the order you use when you apply linear indexing (that is, index a matrix with a single number). For example, let
A = [7 8 6 2
9 0 3 5
6 3 2 1];
Then A(4) gives 8.
With this in mind, it's easy to guess that what sum(A,1) does is traverse elements consecutively: A(1)+A(2)+A(3) to obtain the sum of the first column, then A(4)+A(5)+A(6) to sum the second column, etc. In contrast, sum(A,2) proceeds in steps of size(A,1) (3 in this example): A(1)+A(4)+A(7)+A(10) to compute the sum of the first row, etc.
As a side note, this is probably related with the observed fact that sum(A,1) is faster than sum(A,2).
I'm really not sure what you are asking. sum takes two inputs, the first of which is a multidimensional array A, say.
Now let's take sA = size(A), and d between 1 and ndims(A).
To understand what B = sum(A,d) does, first we find out what the size of B is.
That's easy, sB = sA; sB(d) = 1;. So in a way, it will "reduce" the size of A along dimension d.
The rest is trivial: every element in B is the sum of elements in A along dimension d.
Basically, sum(A) = sum(A,1) which outputs the sum of the columns in the matrix. 1 indicates the columns. So, sum(A,2) outputs the sum of the rows in the matrix. 2 indicating the rows. More than that, the sum command will output the entire matrix because there is only 2 dimensions (rows and columns)

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

Finding index of vector from its original matrix

I have a matrix of 2d lets assume the values of the matrix
a =
17 24 1 8 15
23 5 7 14 16
4 6 13 20 22
10 12 19 21 3
17 24 1 8 15
11 18 25 2 9
This matrix is going to be divided into three different matrices randomly let say
b =
17 24 1 8 15
23 5 7 14 16
c =
4 6 13 20 22
11 18 25 2 9
d =
10 12 19 21 3
17 24 1 8 15
How can i know the index of the vectors in matrix d for example in the original matrix a,note that the values of the matrix can be duplicated.
for example if i want to know the index of {10 12 19 21 3} in matrix a?
or the index of {17 24 1 8 15} in matrix a,but for this one should return only on index value?
I would appreciate it so much if you can help me with this. Thank you in advance
You can use ismember with the 'rows' option. For example:
tf = ismember(a, c, 'rows')
Should produce:
tf =
0
0
1
0
0
1
To get the indices of the rows, you can apply find on the result of ismember (note that it's redundant if you're planning to use this vector for matrix indexing). Here find(tf) return the vector [3; 6].
If you want to know the number of the row in matrix a that matches a single vector, you either use the method explained and apply find, or use the second output parameter of ismember. For example:
[tf, loc] = ismember(a, [10 12 19 21 3], 'rows')
returns loc = 4 for your example. Note that here a is the second parameter, so that the output variable loc would hold a meaningful result.
Handling floating-point numbers
If your data contains floating point numbers, The ismember approach is going to fail because floating-point comparisons are inaccurate. Here's a shorter variant of Amro's solution:
x = reshape(c', size(c, 2), 1, []);
tf = any(all(abs(bsxfun(#minus, a', x)) < eps), 3)';
Essentially this is a one-liner, but I've split it into two commands for clarity:
x is the target rows to be searched, concatenated along the third dimension.
bsxfun subtracts each row in turn from all rows of a, and the magnitude of the result is compared to some small threshold value (e.g eps). If all elements in a row fall below it, mark this row as "1".
It depends on how you build those divided matrices. For example:
a = magic(5);
d = a([2 1 2 3],:);
then the matching rows are obviously: 2 1 2 3
EDIT:
Let me expand on the idea of using ismember shown by #EitanT to handle floating-point comparisons:
tf = any(cell2mat(arrayfun(#(i) all(abs(bsxfun(#minus, a, d(i,:)))<1e-9,2), ...
1:size(d,1), 'UniformOutput',false)), 2)
not pretty but works :) This would be necessary for comparisons such as: 0.1*3 == 0.3
(basically it compares each row of d against all rows of a using an absolute difference)