Matrix index from vector - matlab

In MATLAB, I want to retrieve the value of a particular position in a matrix through a vector
v = [1, 2, 3, 4];
A(v)
A(v(:))
how can I do that?
The length of the vector is not fixed so I cannot hardcode A(v(1), v(2), v(3), v(4)).

Convert v to a cell-array (say cellv) using num2cell and then extract elements of cellv as comma separated values to index A and implement A(v(1), v(2), v(3), v(4), ... v(n)) in a generalised manner.
cellv = num2cell(v);
A(v{:})

Related

Extracting a matrix from a cell vector in MATLAB

A sparse matrix is a large matrix with almost all elements of the same
value (typically zero). The normal representation of a sparse matrix
takes up lots of memory when the useful information can be captured
with much less. A possible way to represent a sparse matrix is with a
cell vector whose first element is a 2-element vector representing the
size of the sparse matrix. The second element is a scalar specifying
the default value of the sparse matrix. Each successive element of the
cell vector is a 3-element vector representing one element of the
sparse matrix that has a value other than the default. The three
elements are the row index, the column index and the actual value.
Write a function called "sparse2matrix" that takes a single input of a
cell vector as defined above and returns the output argument called
"matrix", the matrix in its traditional form. Consider the following
run:
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
matrix = sparse2matrix(cellvec)
matrix =
0 3 0
0 -3 0
Good morning/afternoon/night, everyone
I was wondering if you could help me with this.
I am trying to complete this, but I am not sure how to deal with this. I understand that I am interested in the first part of the cell vector, but I am not sure about how to tell Matlab I need that. This is my code:
function matrix = sparse2matrix(x)
A = [2 3];
B = 0;
C = [1, 2, 3];
x = {A, 0, C};
matrix = cell2mat(x);
end
The result of this code is different from the result I showed above.
I am not getting the right answer and honestly I do not know what to do, so I would appreciate if you guide me a little bit.
Not the most elegant way of doing it but it gets the job done. Uses the cell2mat() function and indexing to grab the necessary values for each step. A for-loop is then used to obtain the 3-element vectors that is used to change the array values from the default values in the respective indices.
cellvec = {[2 3], 0, [1 2 3], [2 2 -3]};
[matrix] = sparse2matrix(cellvec)
function [matrix] = sparse2matrix(x)
Matrix_Size = cell2mat(x(1,1));
Matrix_Height = Matrix_Size(1);
Matrix_Width = Matrix_Size(2);
Default_Value = cell2mat(x(1,2));
matrix = Default_Value*ones(Matrix_Height,Matrix_Width);
Triplets = x(3:end);
Number_Of_Triplets = length(Triplets);
for Triplet_Index = 1: Number_Of_Triplets
Current_Triplet = cell2mat(Triplets(1,Triplet_Index));
Row = Current_Triplet(1,1);
Column = Current_Triplet(1,2);
Value = Current_Triplet(1,3);
matrix(Row,Column) = Value;
end
end
Explanation:
The first line in the local function sparse2matrix() indicates to retrieve row 1, column 1 of the cell array x and then convert it to a matrix. The conversion is done using the cell2mat() function.
Matrix_Size = cell2mat(x(1,1));
Results in:
Matrix_Size = [2 3]
The following line indicates to grab index 1 of the previous array Matrix_Size. This will be used to determine the height of the output array matrix. This is done in a similar fashion to evaluate the Matrix_Width using index 2.
Matrix_Height = Matrix_Size(1);
Results in:
Matrix_Height = 2
Ran using MATLAB R2019b

Matlab - Access elements form each column using a vector containing the rows [duplicate]

I'm writing a MATLAB function to read out data into an n-dimensional array (variable dimension size). I need to be able to access a specific point in the Matrix (to write to it or read it, for example), but I don't know ahead of time how many indexes to specify.
Currently I have a current_point vector which I iterate through to specify each index, and a max_points vector which specifies the size of the array. So, if for example I wanted a 3-dimensional array of size 1000-by-15-by-3, max_points = [1000 15 3], and current_point iterates from [1, 1, 1] to [1000, 15, 3] ([1, 1, 1] -> [1000, 1, 1] -> [1, 2, 1] -> [1000, 2, 1] ->...). What I'd like to be able to do is feed current_point as an index to the matrix like so:
output_matrix(current_point) = val
But apparently something like output_matrix([1 2 3]) = val will just set outputmatrix(1:3) = 30. I can't just use dummy variables because sometimes the matrix will need 3 indexes, other times 4, other times 2, etc, so a vector of variable length is really what I need here. Is there a simple way to use a vector as the points in an index?
Using the function sub2ind to create a linear index is the typical solution to this problem, as shown in this closely-related question. You could also compute a linear index yourself instead of calling sub2ind.
However, your case may be simpler than those in the other questions I linked to. If you're only ever indexing a single point with your current_point vector (i.e. it's just an n-element vector of subscripts into your n-dimensional matrix), then you can use a simple solution where you convert current_point to a cell array of subscripts using the function num2cell and use it to create a comma-separated list of indices. For example:
current_point = [1 2 3 ...]; % A 1-by-n array of subscripts
subCell = num2cell(current_point); % A 1-by-n cell array of subscripts
output_matrix(subCell{:}) = val; % Update the matrix point
The operation subCell{:} creates the equivalent of typing subCell{1}, subCell{2}, ..., which is the equivalent of typing current_point(1), current_point(2), ....
I know it is too late but for anybody who will find this topic. the easiest way that work for me is to use: diag(A (x(:),y(:)) );
unfortunately this works only if you need to get values from the matrix, not for changing values
You can use the sub2ind function to get the linear index from the subscript.
Example:
A=magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
selectElement={2,3}; %# get the element at position 2,3 in A.
indx=sub2ind(size(A),selectElement{:});
A(indx)
ans =
10
In the above example, I've stored the subscripts (can be any number of dimensions) as a cell. If you have it stored as a vector, simply use num2cell() to convert it to a cell.
You can now easily assign a value to this as A(indx)=value;. I've used different variables than yours to keep the answer general, but the idea is the same and you just need to replace the variable names.
You also mentioned in your post that you're looping from (1,1,1) till some value, (1000,15,3) and assigning a value to each of these points. If you're looping along the columns, you can replace this entire operation with a vectorized solution.
Let finalElement={1000,15,3} be the final step of the loop. As before, find the linear index as
index=sub2ind(size(A),finalElement{:});
Now if you have the values you assign in the loop stored as a single vector, values, you can simply assign it in a single step as
A(1:index)=values;

how to insert elements of matrix into cell array at indices specified by another column of the matrix

I have a matrix A which is a n X 2 matrix of floats with the second column in each row representing the column index of the value in the first column. I would ideally like to vectorize the insertion of elements in the first column of A in the row rowIndex and their respective columns as specified by A(:,2).
The pseudo-code for what I am looking to achieve is as follows:
myCellArray = cell(n X n)
%rowIndex is some predefined integer.
rowIndex
%A is my n X 2 matrix of values and corresponding column indices.
A
myCellArray{(rowIndex*ones(size(A(:,1),1),1)),A(:,2)} = A(:,1)
I have provided code for what I have tried at the bottom although I have tried something similar to the last line and it has failed hence I was wondering how something like this would work in MATLAB. Basically if my question is confusing, I am looking to vectorize insertion of elements into cell array by using a vector of indices and vector of values to insert at each index.
a{1,z(:,2)} = z(:,1)
Here I am trying to insert all values in the first column of z matrix into the cells indexed by 1 and the corresponding entry in the second column of z into the cell array.
Use
a(1,z(:,2)) = mat2cell(z(:,1), ones(1,size(z,1)), 1);
For example, with
z = [1 2
3 4];
this results in
a =
[] [1] [] [3]

How to transpose a cell of Mx1 cells and vectors?

I have a 1xN cell, call it X, whose components X{i} (for i in {1, 2, ..., N}) are either Mx1 cells of strings or Mx1 numeric vectors.
NOTE: the fact that X contains both text cells and numeric vectors precludes using cell2mat here:
>> tmp = cell2mat(X);
Error using cell2mat (line 46)
All contents of the input cell array must be of the same data type.
My question is:
What's MATLAB's "idiomatic" way to transpose this data into an array of M 1xN cells?
EDIT: To be clear, the data structure I want to arrive at, let's call it Y, is an M-long array of 1xN cells (each consisting of a mixture of numbers and strings). E.g., if N=2, and if X{1} is an Mx1 cell of strings, and X{2} is an Mx1 vector of doubles, then the desired data structure Y is such that, for any 1 ≤ i ≤ M, Y(i,:) is a 1x2 cell whose first element is the i-th string in X{1} and whose second element is the i-th double in X{2}. I.e. Y(i,:) would be the same as the 1x2 cell Yi defined as follows
xi1 = X(i, 1);
xi2 = X(i, 2);
Yi = {xi1{1} xi2{1}};
(Sorry for the awkwardness! I just can't find a MATLAB expression for Yi directly in terms X and i, without having to create intermediate variables xi1 and xi2.)
First of all, to my knowledge there is no 'idiomatic' way of doing that i Matlab. Remember, we're talking about a complex data structure with nested cells and differing types.
I tried to cook up a solution based on cellfun. It quickly got complicated and I didn't even succeed. So instead I would recommend doing a simple double for loop and a if like this:
for a=1:size(X,2),
for b=1:size(X{a},1),
if iscell(X{a}),
Y{a,b} = X{a}{b};
else
Y{a,b} = X{a}(b);
end
end
end
If X = {{'s1';'s2'} [3; 4]} then this solution will give Y = {'s1' 3 ;'s2' 4}.
As you see I have flattened the cell to one depth. To get your 1xN vectors, do Y{1,:}
Hope it helps
If each cell in X contains a vector of the same size convert it to a matrix, transpose that matrix and then convert it back to a cell array?
tmp = cell2mat(X);
Y = mat2cell(tmp', ...);
Here is the function:
feval(#(y) feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), cellfun(#(x) feval(#(varargin) varargin{3-varargin{1}}(), iscell(x),x,num2cell(x)),y,'un',0)), {{'1','2','3'},[4 5 6],{7,8,9}})
Or stored as a function name:
transpose_nest = #(cell_nest) feval(#(y) feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), cellfun(#(x) feval(#(varargin) varargin{3-varargin{1}}(),iscell(x),x,num2cell(x)),y,'un',0)), cell_nest);
transpose_nest({{'1','2','3'},[4 5 6],{7,8,9}})
{{'1',4,7},{'2',5,8},{'3',6,9}}
It is based on a Matlab equivalent of Scheme's (apply map list '(("1" "2" "3") (4 5 6) (7 8 9))) that only works on sub cells:
feval(#(x) cellfun(#(varargin)[varargin],x{:},'un',0), {{'1','2','3'},{4,5,6},{7,8,9}})
{{'1',4,7},{'2',5,8},{'3',6,9}}
The extra part:
#(x) feval(#(varargin) varargin{3-varargin{1}}(), iscell(x), x, num2cell(x))
is an if statement within an anonymous function that calls num2cell if any sub element is a vector

Use a vector as an index to a matrix

I'm writing a MATLAB function to read out data into an n-dimensional array (variable dimension size). I need to be able to access a specific point in the Matrix (to write to it or read it, for example), but I don't know ahead of time how many indexes to specify.
Currently I have a current_point vector which I iterate through to specify each index, and a max_points vector which specifies the size of the array. So, if for example I wanted a 3-dimensional array of size 1000-by-15-by-3, max_points = [1000 15 3], and current_point iterates from [1, 1, 1] to [1000, 15, 3] ([1, 1, 1] -> [1000, 1, 1] -> [1, 2, 1] -> [1000, 2, 1] ->...). What I'd like to be able to do is feed current_point as an index to the matrix like so:
output_matrix(current_point) = val
But apparently something like output_matrix([1 2 3]) = val will just set outputmatrix(1:3) = 30. I can't just use dummy variables because sometimes the matrix will need 3 indexes, other times 4, other times 2, etc, so a vector of variable length is really what I need here. Is there a simple way to use a vector as the points in an index?
Using the function sub2ind to create a linear index is the typical solution to this problem, as shown in this closely-related question. You could also compute a linear index yourself instead of calling sub2ind.
However, your case may be simpler than those in the other questions I linked to. If you're only ever indexing a single point with your current_point vector (i.e. it's just an n-element vector of subscripts into your n-dimensional matrix), then you can use a simple solution where you convert current_point to a cell array of subscripts using the function num2cell and use it to create a comma-separated list of indices. For example:
current_point = [1 2 3 ...]; % A 1-by-n array of subscripts
subCell = num2cell(current_point); % A 1-by-n cell array of subscripts
output_matrix(subCell{:}) = val; % Update the matrix point
The operation subCell{:} creates the equivalent of typing subCell{1}, subCell{2}, ..., which is the equivalent of typing current_point(1), current_point(2), ....
I know it is too late but for anybody who will find this topic. the easiest way that work for me is to use: diag(A (x(:),y(:)) );
unfortunately this works only if you need to get values from the matrix, not for changing values
You can use the sub2ind function to get the linear index from the subscript.
Example:
A=magic(4)
A =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
selectElement={2,3}; %# get the element at position 2,3 in A.
indx=sub2ind(size(A),selectElement{:});
A(indx)
ans =
10
In the above example, I've stored the subscripts (can be any number of dimensions) as a cell. If you have it stored as a vector, simply use num2cell() to convert it to a cell.
You can now easily assign a value to this as A(indx)=value;. I've used different variables than yours to keep the answer general, but the idea is the same and you just need to replace the variable names.
You also mentioned in your post that you're looping from (1,1,1) till some value, (1000,15,3) and assigning a value to each of these points. If you're looping along the columns, you can replace this entire operation with a vectorized solution.
Let finalElement={1000,15,3} be the final step of the loop. As before, find the linear index as
index=sub2ind(size(A),finalElement{:});
Now if you have the values you assign in the loop stored as a single vector, values, you can simply assign it in a single step as
A(1:index)=values;