This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How can I change the values of multiple points in a matrix?
I have a matrix A and three vectors of the same length, r, holding the indexes of the rows to assign to, c, holding the indexes of the columns to assign to, and v containing the actual values to assign.
What I want to get is A(r(i),c(i))==v(i) for all i. But doing
A(r,c)=v;
Doesn't yield the correct result as matlab interprets it as choosing every possible combination of r and c and assigning values to it, for instance
n=5;
A=zeros(n);
r=1:n;
c=1:n;
A(r,c)=1;
Yields a matrix of ones, where I would like to get the identity matrix since I want A(r(i),c(i))==1 for each i, that is only elements on the diagonal should be affected.
How can I achieve the desired result, without a for loop?
OK, I've found the answer - one needs to use linear indexing, that is convert the column\row pairs into a single index:
idx = sub2ind(size(A), r,c);
A(idx)=v;
Related
This question already has answers here:
Use a vector as an index to a matrix
(3 answers)
Closed 4 years ago.
Is there a way in Matlab to select a matrix element based off the elements in a vector? I don't think my description is clear, but what I effectively want to do is something similar to:
A=zeros(3,3,3) %3d matrix
A(1,1,2)=5
b=[1,1,2]
A(b)=5
Meaning, some easy way to select one element from a matrix using the entries in a vector as arguments. This exact example does not work because the last line counts b as a single argument, not three. I could write A(b(1),b(2),b(3)) but what I'm really looking for here is if there's a nice way of doing.
Method 1: Use sub2ind to find the linear index
You can define a function called findLinearIndex such that it convert the vector elements to the linear index of A:
findLinearIndex = #(A,b) sub2ind(size(A), b(1), b(2), b(3))
A(findLinearIndex(A,b)) = 5
Method 2: Convert the vector to cell array by num2cell
Then, you can use {:} to get the index
b_cell = num2cell(b) ;
A(b_cell{:}) = 5
This question already has answers here:
Building a matrix by merging the same row vector multiple times
(2 answers)
Closed 5 years ago.
I would like to create, from the column matrix A=[1;2;3], another column matrix that repeats A n times. For example, being n=3, the new matrix would be B=[1;2;3;1;2;3;1;2;3]. Is there a way to to that (preferably without using loops)?
Thank you.
You can use repmat it is a fantastic function:
repmat(A,[n,1])
The first value of the second parameter is repetitions in the first dimension (columns), the second in the second dimension (rows) etc.
Another way to do it:
A2=A(:,ones(1,n));
B=A2(:)
Another way is to do using padarray.
a = [1 2 3]
b = padarray(a, [2 0], 'post', 'circular')
post means add to the end of the array, circular pads with circular repetition of elements.
This question already has an answer here:
How to use reshape in Matlab?
(1 answer)
Closed 7 years ago.
I found the following function call:
reshape(A, 1, [])
This flattens matrix A colum major. I am trying to understand the call. The function documentation says after A there should be a size vector for the reshaped matrix, but in here there is a one followed by [] instead of a two-vector. Is this a way of saying "Do whatever it takes so the matrix will have one row, I don't care what the width is"?
How come Matlab lets you exchange one argument for two like this? I tried googling around and did not find an explanation, and I want to understand what's going on here.
[] is an empty matrix. In many MATLAB built-in functions, an empty matrix is interpreted to mean "use the default argument here" or "automatically determine this value". Occasionally it is used to disambiguate two meanings of a function, as with the max function, where max(A,2) compares each element of A to 2 and returns the larger, while max(A,[],2) finds the largest element of each row.
If you read the help for reshape, you will see the following:
You can specify a single dimension size of [] to have the dimension size automatically calculated, such that the number of elements in B matches the number of elements in A. For example, if A is a 10-by-10 matrix, then reshape(A,2,2,[]) reshapes the 100 elements of A into a 2-by-2-by-25 array.
This question already has answers here:
Index Exceeds Dimensions/Nested For loop issues
(2 answers)
Closed 9 years ago.
I am using a nested for loop to do the following functions:
I am going column by column in a TranLog matrix (W X N size) and finding which row has a non zero value
Based upon the row location of this non-zero Value in TranLog, I am calling the vector associated with that row # in the matrix Order.
The for loop is as follows:
for jj=1:W;
for ii=1:N;
if TranLog(ii,jj)>0.5
test=Order(ii,:);
end
end
end
When I am running this the number of vectors output are smaller than it should be. For example: If Tranlog is 23X5 and Order is 23X6, if there are 23 non zeros spread throughout the TranLog matrix (there is one non-zero value per row in TranLog) I am only getting 13 ouput vectors from the Order matrix. I am not sure why this isn't running to completion, I don't receive an error but it doesnt ouput as many vectors as I am expecting.
Here's the problem. Your matrix has W rows and N columns, yet the W index, jj, is indexing columns rather than rows in line 3. The opposite is happening with ii, the index of N. Switch those around and you should be good to go!
for jj=1:W;
for ii=1:N;
if TranLog(jj,ii)>0.5
test=Order(ii,:);
end
end
end
I'm currently working in an area that is related to simulation and trying to design a data structure that can include random variables within matrices. To motivate this let me say I have the following matrix:
[a b; c d]
I want to find a data structure that will allow for a, b, c, d to either be real numbers or random variables. As an example, let's say that a = 1, b = -1, c = 2 but let d be a normally distributed random variable with mean 0 and standard deviation 1.
The data structure that I have in mind will give no value to d. However, I also want to be able to design a function that can take in the structure, simulate a uniform(0,1), obtain a value for d using an inverse CDF and then spit out an actual matrix.
I have several ideas to do this (all related to the MATLAB icdf function) but would like to know how more experienced programmers would do this. In this application, it's important that the structure is as "lean" as possible since I will be working with very very large matrices and memory will be an issue.
EDIT #1:
Thank you all for the feedback. I have decided to use a cell structure and store random variables as function handles. To save some processing time for large scale applications, I have decided to reference the location of the random variables to save time during the "evaluation" part.
One solution is to create your matrix initially as a cell array containing both numeric values and function handles to functions designed to generate a value for that entry. For your example, you could do the following:
generatorMatrix = {1 -1; 2 #randn};
Then you could create a function that takes a matrix of the above form, evaluates the cells containing function handles, then combines the results with the numeric cell entries to create a numeric matrix to use for further calculations:
function numMatrix = create_matrix(generatorMatrix)
index = cellfun(#(c) isa(c,'function_handle'),... %# Find function handles
generatorMatrix);
generatorMatrix(index) = cellfun(#feval,... %# Evaluate functions
generatorMatrix(index),...
'UniformOutput',false);
numMatrix = cell2mat(generatorMatrix); %# Change from cell to numeric matrix
end
Some additional things you can do would be to use anonymous functions to do more complicated things with built-in functions or create cell entries of varying size. This is illustrated by the following sample matrix, which can be used to create a matrix with the first row containing a 5 followed by 9 ones and the other 9 rows containing a 1 followed by 9 numbers drawn from a uniform distribution between 5 and 10:
generatorMatrix = {5 ones(1,9); ones(9,1) #() 5*rand(9)+5};
And each time this matrix is passed to create_matrix it will create a new 10-by-10 matrix where the 9-by-9 submatrix will contain a different set of random values.
An alternative solution...
If your matrix can be easily broken into blocks of submatrices (as in the second example above) then using a cell array to store numeric values and function handles may be your best option.
However, if the random values are single elements scattered sparsely throughout the entire matrix, then a variation similar to what user57368 suggested may work better. You could store your matrix data in three parts: a numeric matrix with placeholders (such as NaN) where the randomly-generated values will go, an index vector containing linear indices of the positions of the randomly-generated values, and a cell array of the same length as the index vector containing function handles for the functions to be used to generate the random values. To make things easier, you can even store these three pieces of data in a structure.
As an example, the following defines a 3-by-3 matrix with 3 random values stored in indices 2, 4, and 9 and drawn respectively from a normal distribution, a uniform distribution from 5 to 10, and an exponential distribution:
matData = struct('numMatrix',[1 nan 3; nan 2 4; 0 5 nan],...
'randIndex',[2 4 9],...
'randFcns',{{#randn , #() 5*rand+5 , #() -log(rand)/2}});
And you can define a new create_matrix function to easily create a matrix from this data:
function numMatrix = create_matrix(matData)
numMatrix = matData.numMatrix;
numMatrix(matData.randIndex) = cellfun(#feval,matData.randFcns);
end
If you were using NumPy, then masked arrays would be the obvious place to start, but I don't know of any equivalent in MATLAB. Cell arrays might not be compact enough, and if you did use a cell array, then you would have to come up with an efficient way to find the non-real entries and replace them with a sample from the right distribution.
Try using a regular or sparse matrix to hold the real values, and leave it at zero wherever you want a random variable. Then alongside that store a sparse matrix of the same shape whose non-zero entries correspond to the random variables in your matrix. If you want, the value of the entry in the second matrix can be used to indicate which distribution (ie. 1 for uniform, 2 for normal, etc.).
Whenever you want to get a purely real matrix to work with, you iterate over the non-zero values in the second matrix to convert them to samples, and then add that matrix to your first.