combine row and columns in matlab for series - arrays

everyone
I have problem when make iteration for two variable but, it's combine just in one vector or array
At first i write my input for iteration w(0) as w
w=[1 50];
for number 1, I use array
e=0:1:(n-1);
f=0:2:(2*n-2); %for 50 in column 2.
I try to use this code
w=[1 50];
ww=kron(ones((n),1),w)
e=0:1:(n-1);
f=0:2:(2*n-2);
r=[e',f']
x=ww+r
and the output is
ww =
1 50
1 50
1 50
1 50
1 50
1 50
r =
0 0
1 2
2 4
3 6
4 8
5 10
x =
1 50
2 52
3 54
4 56
5 58
6 60
I want x is output just in one array, in example
x =
1
50
2
52
3
54
4
56
5
58
6
60
where w=[1 50] can be use difference addition for iteration

Apply this to your x matrix:
x = reshape(x.',[],1);
See reshape doc for details.

Here is a simple method to create your vector from scratch:
x = [1:6;50:2:60];
x(:)
Or with your variables:
x = [e; f];
x(:)

Related

How can I need multiply group of elements instead of one element in matrices multiplication

Suppose I have a matrix of dimension [4x4], and a vector of [16x1], I need to multiply every 4 element in the vector in one element in the matrix, (instead of multiplying element in row by element in vector), how can I do that using loop ?
For example here below, the results of the first four elements in the resulted vector as shown in the below example, then the same thing for the second, third and fourth rows in the matrix. :
So the results in that example is supposed to be [16x1]
Thank you
Using kron you can use this one-liner:
%A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
%v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
sum(kron(A,ones(4,4)).'.*v).'/4
I use the kronecker tensor product to "replicate" 4x4 time the A matrice. After that it's pure algebra.
This is just matrix multiplication in disguise... If your tall vector was a matrix of the same size as the matrix shown, where each highlighted block is a row, it's matrix multiplication. We can set this up, then reshape back into a vector.
You can use indexing to turn this into simple matrix multiplication. A question I answered already today details how the below indexing works using bsxfun, then we just reshape at the end:
% Setup
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
% Matrix mutliplication
r = numel(v)/size(A,1);
b = A * v( bsxfun( #plus, (1:r:numel(v)).', 0:r-1 ) );
% Make result a column vector
b = reshape( b.', [], 1 );
See if this is what you want:
A = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16];
v = [2 2 2 2 0 0 0 0 1 1 1 1 3 3 3 3].';
r = reshape(sum(bsxfun(#times, permute(A, [3 2 1]), permute(reshape(v, 1, [], size(A,2)), [2 3 1])), 2), [], 1);
which gives
r =
17
17
17
17
41
41
41
41
65
65
65
65
89
89
89
89
There are details that I assumed, but this shoudl do the trick:
A=reshape(1:16,4,4).';
b=repelem([2,0,1,3],1,4).';
c=[];
for row=1:size(A,1)
c=[ c; sum(reshape(repelem(A(row,:),4).*b.',4,[]),2)];
end
I am assuming here that your demo for the vector is just a bad example and that you wont have repeated values, otherwise an easier version can be achieved by just not doing 3/4ths of the multiplications.
If you do not have access to repelem, have a look at alterative codes that do the same thing:Element-wise array replication in Matlab

Sort array in descending order but keep NaNs at the end

I have an array:
Data = [10 20 30 50 40 60 NaN NaN 70 80; 1 2 3 4 5 6 7 8 9 10];
The first row represents the data and the second one contains the indices for the first row.
I want to arrange the first row in descending order, but with the correct indices.
Therefore, my output should be like
N_Data = [80 70 60 50 40 30 20 10 NaN NaN; 10 9 6 4 5 3 2 1 8 7];
I don't really care about the NaNs so it is ok to eliminate them from the array N_Data
You can just sort the negative of your data in the default ascending order which will automatically place the NaN values at the end. You can then negate the result to get the original values
result = -sortrows(-Data.').'
% 80 70 60 50 40 30 20 10 NaN NaN
% 10 9 6 4 5 3 2 1 8 7
And if you want to remove NaN values
result = result(:, any(isnan(result), 1));
Here you can find two options, inspired by this answers applied for your case:
%// Option 1
Data = [10 20 30 50 40 60 NaN NaN 70 80; 1 2 3 4 5 6 7 8 9 10]
Data(isnan(Data)) = -Inf;
N_Data = sortrows(Data.',-1).'
N_Data(isinf(N_Data)) = NaN
%// Option 2
Data = [10 20 30 50 40 60 NaN NaN 70 80; 1 2 3 4 5 6 7 8 9 10]
[sortedData, sortedIndices] = sort(Data(1,:),'descend')
N_Data = [sortedData; sortedIndices]
mask = isnan(sortedData)
N_Data = [ N_Data( :,~mask), N_Data( :, mask) ]
N_Data =
80 70 60 50 40 30 20 10 NaN NaN
10 9 6 4 5 3 2 1 7 8
If you don't care about the NaNs, the options can be shortened to:
%// Option 1
Data(isnan(Data)) = -Inf;
N_Data = sortrows(Data.',-1).'
N_Data(:,isinf(N_Data(1,:))) = []
%// Option 2
[sortedData, sortedIndices] = sort(Data(1,:),'descend')
N_Data = [sortedData; sortedIndices]
N_Data = N_Data( :,~isnan(sortedData) )
Explanation:
%// N_Data = N_Data( :,~isnan(sortedData) )
x = isnan(sortedData) %// creates logical mask, where NaNs exist
y = ~x %// negates mask, to mask values which are not Nan
N_Data = N_Data( :,y ) %// selects all rows and masked columns without NaN
N_Data =
80 70 60 50 40 30 20 10
10 9 6 4 5 3 2 1
Try using sortrows(Data.',-1).'.
It sorts rows and you want columns sorted, hence the .'. The -1 option is for descending order.

Matlab replace element between 2 matrix

I have two matrix M x N, For simplicity, we take 4x4:
Matrix A:
1 4 2 5
4 5 8 2
3 4 5 6
2 3 5 8
Matrix B:
10 11 12 13
56 11 23 45
34 44 33 25
25 63 35 78
If an element of matrix A is greater then 5, then we change it from matrix B.
At the end we must get a matrix C:
1 4 2 5
4 5 23 2
3 4 5 25
2 3 5 78
How can I make it, should I use something like logical indexing..
Yes, you should use logical indexing:
C = A;
C(C>5) = B(C>5);
This means that every element in C that is >5 is set to the corresponding value in B.
or
C = A.*(A<=5) + B.*(A>5);
The comparisons in the parentheses create arrays with 0 and 1, so the first multiplication sets all elements of A to zero that should be taken from B, and second multiplication sets all elements of B to zero that should be taken from A.

matlab retrieve elements in a vector corresponding to matrix of indexes

I have a vector v.
I also have a matrix M of size TxN with each column corresponding to T indices of v.
For example: M(:,1) is the set of indices [1,2,12,5,4] (here T = 5).
I want to have a matrix O of size TxN with O(:,i) = v(M(:,i)) for all i.
Is there a way to do that without using for loops ?
Thanks a lot
Very easy: just use
O = v(M);
Example with T=3, N=4:
>> v = (10:10:50).'
v =
10
20
30
40
50
>> M = randi(5,T,N)
M =
5 3 5 3
2 3 1 4
2 4 5 3
>> O = v(M)
O =
50 30 50 30
20 30 10 40
20 40 50 30

Vectorize the sum of unique columns

There are multiple occurrence of same combination of values in different rows of matlab, for example 1 1 in first and second row. I want to remove all those duplicates but adding the values in third column. In case of 1 1 it will be 7. Finally I want to create a similarity matrix as shown below in Answer. I don't mind 2*values in diagonals because I will not be considering diagonal elements in further work. The code below does this but it is not vectorized. Can this be vectorized somehow. Example is given below.
datain = [ 1 1 3;
1 1 4;
1 2 5;
1 2 4;
1 2 3;
1 3 8;
1 3 7;
1 3 12;
2 2 22;
2 2 77;
2 3 111;
2 3 113;
3 3 456;
3 3 568];
cmp1=unique(datain(:,1));
cmp1sz=size(cmp1,1);
cmp2=unique(datain(:,2));
cmp2sz=size(cmp2,1);
thetotal=zeros(cmp1sz,cmp2sz);
for i=1:size(datain,1)
for j=1:cmp1sz
for k=1:cmp2sz
if datain(i,1)==cmp1(j,1) && datain(i,2)== cmp2(k,1)
thetotal(j,k)=thetotal(j,k)+datain(i,3);
thetotal(k,j)=thetotal(k,j)+datain(i,3);
end
end
end
end
The answer is
14 12 27
12 198 224
27 224 2048
This is a poster case for using ACCUMARRAY.
thetotal = accumarray(datain(:,1:2),datain(:,3),[],#sum,0);
%# to make the array symmetric, you simply add its transpose
thetotal = thetotal + thetotal'
thetotal =
14 12 27
12 198 224
27 224 2048
EDIT
So what if datain does not contain only integer values? In this case, you can still construct a table, but e.g. thetotal(1,1) will not correspond to datain(1,1:2) == [1 1], but to the smallest entry in the first two columns of datain.
[uniqueVals,~,tmp] = unique(reshape(datain(:,1:2),[],1));
correspondingIndices = reshape(tmp,size(datain(:,1:2)));
thetotal = accumarray(correspondingIndices,datain(:,3),[],#sum,0);
The value at [1 1] now corresponds to the row [uniqueVals(1) uniqueVals(1)] in the first two cols of datain.

Resources