Filling the pixels with values of another matrix - matlab

Say you have two matrices as follows:
A = [1 0.2 1; 0.4 0.4 1; 1 0.6 1; 0.9 0.7 1];
B = [33 75 250; 6 34 98; 55 3 4; 153 66 30];
Say we want to create a new matrix C that contains the values of B where A=1.
I think in matlab we can do the following for this:
C = B(A==1);
But, how can I fill the other cells with the original values of A, as I think in our case, we will just get a vector with the B elements which their corresponding value in A=1? And, I want C to have the same dimensions of B but with the original values of A that are not equal to 1 instead of having 0 values.

Yes, you can do it like this:
C= A.*(A~=1)+B.*(A==1)
Which gives:
C =
33.0000 0.2000 250.0000
0.4000 0.4000 98.0000
55.0000 0.6000 4.0000
0.9000 0.7000 30.0000

C will have to be initialized anyways, so let's initialize it to A as in C = A;. Then, MATLAB allows you to index the left-hand side as in C(A==1) = B(A==1); to replace all elements in C by those in B for which A == 1. All other elements will stay the same.

Related

Cartesian product of row values of a marix in Matlab

Similarly to this question, I have a matrix with real values (including NaNs) A of dimension mxn in Matlab. I want to construct a matrix B listing row-wise each element of the non-unique Cartesian product of the values contained in As columns which are not NaN. To be more clear consider the following example.
Example:
%m=3;
%n=3;
A=[2.1 0 NaN;
69 NaN 1;
NaN 32.1 NaN];
%Hence, the Cartesian product {2.1,0}x{69,1}x{32.1} is
%{(2.1,69,32.1),(2.1,1,32.1),(0,69,32.1),(0,1,32.1)}
%I construct B by disposing row-wise each 3-tuple in the Cartesian product
B=[2.1 69 32.1;
2.1 1 32.1;
0 69 32.1;
0 1 32.1];
I came up with a solution using cells:
function B = q48444528(A)
if nargin < 1
A = [2.1 0 NaN;
69 NaN 1 ;
NaN 32.1 NaN];
end
% Converting to a cell array of rows:
C = num2cell(A,2);
% Getting rid of NaN values:
C = cellfun(#(x)x(~isnan(x)),C,'UniformOutput',false);
% Finding combinations:
B = combvec(C{:}).';
Output:
B =
2.1000 69.0000 32.1000
0 69.0000 32.1000
2.1000 1.0000 32.1000
0 1.0000 32.1000

Rearranging elements in a row matlab

I have two matrices in Matlab.
A =
and
B =
I want to assign the elements having the same cell-value according to it's corresponding column number in A matrix and move the elements there. I want to map the elements of B with A so that B elements also moves in that position.
I want this
A =
And therefore,
B =
Is there a way to do this?!
Thanks.
Easiest way I can think of is to create row/column pairs where the rows correspond row locations of the matrix and column locations are the actual elements of the matrix themselves. The values seen at these row/column pairs are again just the matrix values themselves.
You can very easily do this with sparse. Recreating the matrix above and storing this in A:
A = [1 2 5 8; 1 2 4 7];
... I would do it this way:
r = repmat((1:size(A,1)).', 1, size(A,2)); %'
S = full(sparse(r(:),A(:),A(:)));
The first line of code generates row locations for each value in the matrix A, then using sparse to specify row/column pairs and the associated values and we use full to convert to a proper numeric matrix.
We get:
S =
1 2 0 0 5 0 0 8
1 2 0 4 0 0 7 0
You can also do the same for the matrix B. You'd use sparse and specify the third parameter to be B instead:
B = [0.5 0.2 0.6 0.8; 0.4 0.6 0.8 0.9];
S2 = full(sparse(r(:),A(:),B(:)));
We get:
>> S2
S2 =
0.5000 0.2000 0 0 0.6000 0 0 0.8000
0.4000 0.6000 0 0.8000 0 0 0.9000 0

Find the same values in another column in matlab

i want to find same values of number in different column,
for example i have a matrix array:
A = [1 11 0.17
2 1 78
3 4 90
45 5 14
10 10 1]
so as you can see no. 1 in column 1 have the same values in column 2 and column 3, so i want to pick that number and put into another cell or matrix cell
B= [1]
and perform another operation C/B, letting C is equal to:
C= [1
3
5
7
9]
and you will have:
D= [1 11 0.17 1
2 1 78 3
3 4 90 5
45 5 14 7
10 10 1 9]
then after that, values in column 4 have equivalent numbers that we can define, but we will choose only those number that have number 1, or B in theirs row
define:
1-->23
3 -->56
9 --> 78
then we have, see image below:
so how can i do that? is it possible? thanks
Let's tackle your problem into steps.
Step #1 - Determine if there is a value shared by all columns
We can do this intelligently by bsxfun, unique, permute and any and all.
We first need to use unique so that we can generate all possible unique values in the matrix A. Once we do this, we can look at each value of the unique values and see if all columns in A contain this value. If this is the case, then this is the number we need to focus on.
As such, do something like this first:
Aun = unique(A);
eqs_mat = bsxfun(#eq, A, permute(Aun, [3 2 1]));
eqs_mat would generate a 3D matrix where each slice figures out where a particular value in the unique array appeared. As such, for each slice, each column will have a bunch of false values but at least one true value where this true value tells you the position in the column that matched a unique value. The next thing you'll want to do is go through each slice of this result and determine whether there is at least one non-zero value for each column.
For a value to be shared along all columns, a slice should have a non-zero value per column.
We can eloquently determine which value we need to extract by:
ind = squeeze(all(any(eqs_mat,1),2));
Given your example data, we have this for our unique values:
>> B
B =
0.1700
1.0000
2.0000
3.0000
4.0000
5.0000
10.0000
11.0000
14.0000
45.0000
78.0000
90.0000
Also, the last statement I executed above gives us:
>> ind
ind =
0
1
0
0
0
0
0
0
0
0
0
0
The above means that the second location of the unique array is the value we want, and this corresponds to 1. Therefore, we can extract the particular value we want by:
val = Aun(ind);
val contains the value that is shared along all columns.
Step #2 - Given the value B, take a vector C and divide by B.
That's pretty straight forward. Make sure that C is the same size as the total number of rows as A, so:
C = [1 3 5 7 9].';
B = val;
col = C / B;
Step #3 - For each location in A that shares the common value, we want to generate a new fifth column that gives a new value for each corresponding row.
You can do that by declaring a vector of... say... zeroes, then find the right rows that share the common value and replace the values in this fifth column with the values you want:
zer = zeros(size(A,1), 1);
D = [23; 56; 78];
ind2 = any(A == val, 2);
zer(ind2) = D;
%// Create final matrix
fin = [A col zer];
We finally get:
>> fin
fin =
1.0000 11.0000 0.1700 1.0000 23.0000
2.0000 1.0000 78.0000 3.0000 56.0000
3.0000 4.0000 90.0000 5.0000 0
45.0000 5.0000 14.0000 7.0000 0
10.0000 10.0000 1.0000 9.0000 78.0000
Take note that you need to make sure that what you're assigning to the fifth column is the same size as the total number of columns in A.

Checking which rows switched given an original and an altered matrix in Matlab

I've been trying to wrap my head around this for awhile and was hoping to get some insight.
Suppose you have matrix A, then you switched rows until you ended up with matrix B;
A = [1 3 1;
3 2 1;
2 3 1;];
B = [3 2 1;
1 3 1;
2 3 1;];
invA =
0.0000 -1.0000 1.0000
-1.0000 -1.0000 2.0000
3.0000 5.0000 -7.0000
invB =
-1.0000 0.0000 1.0000
-1.0000 -1.0000 2.0000
5.0000 3.0000 -7.0000
How would I document these row switches?. I'm ultimately trying to alter the inverse of B to match with the inverse of A. My conclusion was that given 2 rows switched (aka between rows 1 and 2), the end result of the inverse would be identical except for switching the columns of (1 and 2) of the inverse B.
This is quite a basic algebra question.
You can write your matrix B as a product of a permutation matrix P and A:
B = PA;
(in your example: P = [0 1 0;1 0 0;0 0 1];).
Now you can invert B:
inv( B ) = inv( PA )
The inverse of a product is
= inv(A) * inv(P)
Since matrix P is a permutation matrix: inv(P) = P.'. Thus
= inv(A) * P.'
That is, inv(B) = inv(A) * P.' which means that you apply the permutation P to the columns of inv(A).
Note that a permutation P can represent more than a single switch between rows, moreover, permutations can be multiplies to account for repeated switching of rows.
An important comment: I use inv in this answer to denote the inverse of a matrix. However, when running Matlab and numerically inverting matrices it is un-recommended to use inv function explicitly.

Create vectors associated with each entry of an array and save them in a new matrix

Say i have a matrix like A = [1 2; 3 4], and that i need to create 4, vectors each one associated to one entrance of the matrix, such that the first one goes from -1..1, and second from -2..2, and so forth. Wath i try was
for j=1:2
for k=1:2
W=linspace(-A(j,k),A(j,k),4)
end
end
the problem with that line is that it not save the data.
Also i need that to create a new matrix, such that every row be one of the vectors that i mentioned.
I know that on octave i can do
W=linspace(-A,A,4)
but in MATLAB it doesn't work
If you want 4 values evenly distributed between A(k) and A(k), then you can use an anonymous function in combination with linspace this way:
fun = #(x) linspace(-A(x), A(x), 4)
b = fun(1:numel(A))
b =
-1.00000 -0.33333 0.33333 1.00000
-3.00000 -1.00000 1.00000 3.00000
-2.00000 -0.66667 0.66667 2.00000
-4.00000 -1.33333 1.33333 4.00000
Assuming you want [-1 0 1], [-2 -1 0 1 2] etc, then I suggest using arrayfun like this:
A = [1 2;3 4];
b = arrayfun(#(n) -A(n):A(n), 1:numel(A), 'UniformOutput',0)
b =
{
[1,1] =
-1 0 1
[1,2] =
-3 -2 -1 0 1 2 3
[1,3] =
-2 -1 0 1 2
[1,4] =
-4 -3 -2 -1 0 1 2 3 4
Your approach didn't work because you're overwriting W everytime you loop. The following works:
V = zeros(numel(A),4);
for k=1:numel(A)
W(k,:) = linspace(-A(k),A(k),4);
end
The reason why I only use one index for A is because you may use linear indexing in MATLAB. Remember to allocate memory before you assign values to a matrix inside a loop. "Growing" matrices are very slow.
You can do it like that
W = zeros(4,4);
a = reshape(A, 1, 4);
for i=1:4
W(i,:) = linspace(-a(i), a(i), 4);
end
and you obtain
W =
-1.0000 -0.3333 0.3333 1.0000
-3.0000 -1.0000 1.0000 3.0000
-2.0000 -0.6667 0.6667 2.0000
-4.0000 -1.3333 1.3333 4.0000
If you want to generate a fixed number of values (say 4) for each entry of A, you can achieve it in one line:
>> bsxfun(#times, linspace(-1,1,4), A(:))
ans =
-1.0000 -0.3333 0.3333 1.0000
-3.0000 -1.0000 1.0000 3.0000
-2.0000 -0.6667 0.6667 2.0000
-4.0000 -1.3333 1.3333 4.0000