Making a matrix from another matrix - matlab

I have a matrix with 1 column, x rows. My second matrix has to be the first few values of that matrix concatenated to the last values of that matrix.
Example:
a=[0:1:10]
b=[0,1,9,10]
Question: How do I build b, by using a?

Say the number of values you want to extract off of each end is n. The horzcat command let's you horizontally concatenate matrices.
n=2;
a=[0:1:10];
b=horzcat(a(1:n),a(end-n+1:end))

E.g. for letting b be the first two columns of a and the two last columns of a concatenated: b = [a(:, 1:2), a(:, size(a, 2) - 1:size(a, 2))].
Example:
>> a = [0:1:10]
a =
0 1 2 3 4 5 6 7 8 9 10
>> b = [a(:, 1:2), a(:, size(a, 2) - 1:size(a, 2))]
b =
0 1 9 10

Related

Extract values from 2d array with indices from another array (without loops)

I have an array [2; 3] and a matrix [ 1 3 4 5; 2 4 9 2].
Now I would like to extract the second element from the first row and the third element from the second row and thus obtain [3 ; 9]. I managed it to do it with a loop, but since I'm working with much larger arrays, I would like to avoid these.
You can use sub2ind to convert each of the column subscripts (along with their row subscripts) into a linear index and then use that to index into your matrix.
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
% Compute the linear index using sub2ind
inds = sub2ind(size(A), (1:numel(cols)).', cols);
B = A(inds)
% 3
% 9
Alternately, you could compute the linear indices yourself which is going to be more performant than sub2ind
B = A((cols - 1) * size(A, 1) + (1:numel(cols)).');
% 3
% 9
By exploiting the diag function, you can obtain an elegant one-line solution:
A = [1 3 4 5; 2 4 9 2];
cols = [2; 3];
B = diag(A(:,cols))
% 3
% 9
Here is what diag(A(:,cols)) does:
A(:,cols) selects the columns cols of A, with column k of A(:,cols) corresponding to the column cols(k) of A, giving [3 4; 4 9];
diag returns the diagonal entries of this matrix, thus returning at position k the k-th diagonal element of A(:,cols), which is A(k,cols(k)).

Turning matrix diagonals to columns

I am looking for a matrix operation of the form: B = M*A*N where A is some general square matrix and M and N are the matrices I want to find.
Such that the columns of B are the diagonals of A. The first column the main diagonal, the second the diagonal shifted by 1 from the main and so on.
e.g. In MATLAB syntax:
A = [1, 2, 3
4, 5, 6
7, 8, 9]
and
B = [1, 2, 3
5, 6, 4
9, 7, 8]
Edit:
It seems a pure linear algebra solution doesn't exist. So I'll be more precise about what I was trying to do:
For some vector v of size 1 x m. Then define C = repmat(v,m,1). My matrix is A = C-C.';.
Therefore, A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values.
Those are the diagonals of A; but m is so large that the construction of such m x m matrices causes out-of-memory issues.
I'm looking for a way to extract those diagonals in a way that is as efficient as possible (in MATLAB).
Thanks!
If you're not actually looking for a linear algebra solution, then I would argue that constructing three additional matrices the same size as A using two matrix multiplications is very inefficient in both time and space complexity. I'm not sure it's even possible to find a matrix solution, given my limited knowledge of linear algebra, but even if it is it's sure to be messy.
Since you say you only need the values along some diagonals, I'd construct only those diagonals using diag:
A = [1 2 3;
4 5 6;
7 8 9];
m = size(A, 1); % assume A is square
k = 1; % let's get the k'th diagonal
kdiag = [diag(A, k); diag(A, k-m)];
kdiag =
2
6
7
Diagonal 0 is the main diagonal, diagonal m-1 (for an mxm matrix) is the last. So if you wanted all of B you could easily loop:
B = zeros(size(A));
for k = 0:m-1
B(:,k+1) = [diag(A, k); diag(A, k-m)];
end
B =
1 2 3
5 6 4
9 7 8
From the comments:
For v some vector of size 1xm. Then B=repmat(v,m,1). My matrix is A=B-B.'; A is essentially all differences of values in v but I'm only interested in the difference up to some distance between values.
Let's say
m = 4;
v = [1 3 7 11];
If you construct the entire matrix,
B = repmat(v, m, 1);
A = B - B.';
A =
0 2 6 10
-2 0 4 8
-6 -4 0 4
-10 -8 -4 0
The main diagonal is zeros, so that's not very interesting. The next diagonal, which I'll call k = 1 is
[2 4 4 -10].'
You can construct this diagonal without constructing A or even B by shifting the elements of v:
k = 1;
diag1 = circshift(v, m-k, 2) - v;
diag1 =
2 4 4 -10
The main diagonal is given by k = 0, the last diagonal by k = m-1.
You can do this using the function toeplitz to create column indices for the reshuffling, then convert those to a linear index to use for reordering A, like so:
>> A = [1 2 3; 4 5 6; 7 8 9]
A =
1 2 3
4 5 6
7 8 9
>> n = size(A, 1);
>> index = repmat((1:n).', 1, n)+n*(toeplitz([1 n:-1:2], 1:n)-1);
>> B = zeros(n);
>> B(index) = A
B =
1 2 3
5 6 4
9 7 8
This will generalize to any size square matrix A.

How to distinguish the two picture matrices?

I have a picture matrix A, the size of which is 200*3000 double. And I have another picture matrix B, the size of which is 200*1000 double. The 1000 columns of matrix B exactly comes from the columns of matrix A. My question is:
How to get a matrix C with the same size of matrix A, but only keep the original values of columns in matrix B? I mean the size of matrix C is 200*3000 double, but only 1000 columns have the same values as matrix B. The other 2000 columns will be set to another value d, that is my second question, what is the value I should set for d, so that the picture matrix C can distinguish from picture matrix A?
Use ismember with the 'rows' option. Here's an example:
A = [1 2 3 4; 5 6 7 8]; %// example A
B = [3 10 1; 7 20 5]; %// example B
val = NaN; %// example value to indicate no match
C = A; %// initiallize
ind = ismember(A.',B.','rows'); %// matching columns
C(:,~ind) = val; %// set non-matching columns to val
Equivalently, you coud replace ismember by bsxfun, so that line becomes
ind = any(all(bsxfun(#eq, A, permute(B, [1 3 2])), 1), 3);
In this example,
A =
1 2 3 4
5 6 7 8
B =
3 10 1
7 20 5
C =
1 NaN 3 NaN
5 NaN 7 NaN

average 3rd column when 1st and 2nd column have same numbers

just lets make it simple, assume that I have a 10x3 matrix in matlab. The numbers in the first two columns in each row represent the x and y (position) and the number in 3rd columns show the corresponding value. For instance, [1 4 12] shows that the value of function in x=1 and y=4 is equal to 12. I also have same x, and y in different rows, and I want to average the values with same x,y. and replace all of them with averaged one.
For example :
A = [1 4 12
1 4 14
1 4 10
1 5 5
1 5 7];
I want to have
B = [1 4 12
1 5 6]
I really appreciate your help
Thanks
Ali
Like this?
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7];
[x,y] = consolidator(A(:,1:2),A(:,3),#mean);
B = [x,y]
B =
1 4 12
1 5 6
Consolidator is on the File Exchange.
Using built-in functions:
sparsemean = accumarray(A(:,1:2), A(:,3).', [], #mean, 0, true);
[i,j,v] = find(sparsemean);
B = [i.' j.' v.'];
A = [1 4 12;1 4 14;1 4 10; 1 5 5;1 5 7]; %your example data
B = unique(A(:, 1:2), 'rows'); %find the unique xy pairs
C = nan(length(B), 1);
% calculate means
for ii = 1:length(B)
C(ii) = mean(A(A(:, 1) == B(ii, 1) & A(:, 2) == B(ii, 2), 3));
end
C =
12
6
The step inside the for loop uses logical indexing to find the mean of rows that match the current xy pair in the loop.
Use unique to get the unique rows and use the returned indexing array to find the ones that should be averaged and ask accumarray to do the averaging part:
[C,~,J]=unique(A(:,1:2), 'rows');
B=[C, accumarray(J,A(:,3),[],#mean)];
For your example
>> [C,~,J]=unique(A(:,1:2), 'rows')
C =
1 4
1 5
J =
1
1
1
2
2
C contains the unique rows and J shows which rows in the original matrix correspond to the rows in C then
>> accumarray(J,A(:,3),[],#mean)
ans =
12
6
returns the desired averages and
>> B=[C, accumarray(J,A(:,3),[],#mean)]
B =
1 4 12
1 5 6
is the answer.

Randomly interchange columns of a matrix: Matlab

Suppose
A = [1 2 3 5 7 9
6 5 0 3 2 3]
I want to randomize the position of the matrix column position; to give B like so:
B = [3 9 1 7 2 5
0 3 6 2 5 3]
How can I do this Matlab?
Try
B = A(randperm(length(A)))
Consult the documentation for explanations.
Now that code is formatted properly, it's clear the OP wants column preservation, although randperm is still the easiest option as given by HPM's answer.
idx = randperm(size(A,2)); % Create list of integers 1:n, in random order,
% where n = num of columns
B = A(:, idx); % Shuffles columns about, on all rows, to indixes in idx
You'll want to use the randperm function to generate a random permutation of column indices (from 1 to the number of columns in A), which you can then index A with:
B = A(:, randperm(size(A, 2)));