Repmat function in matlab - matlab

I have been through a bunch of questions about the Repeat function in MatLab, but I can't figure out how this process work.
I am trying to translate it into R, but my problem is that I do not know how the function manipulates the data.
The code is part of a process to make a pairs trading strategy, where the code takes in a vector of FALSE/TRUE expressions.
The code is:
% initialize positions array
positions=NaN(length(tday), 2);
% long entries
positions(shorts, :)=repmat([-1 1], [length(find(shorts)) 1]);
where shorts is the vector of TRUE/FALSE expressions.
Hope you can help.

repmat repeats the matrix you give him [dim1 dim2 dim3,...] times. What your code does is:
1.-length(find(shorts)): gets the amount of "trues" in shorts.
e.g:
shorts=[1 0 0 0 1 0]
length(find(shorts))
ans = 2
2.-repmat([-1 1], [length(find(shorts)) 1]); repeats the [-1 1] [length(find(shorts)) 1] times.
continuation of e.g.:
repmat([-1 1], [length(find(shorts)) 1]);
ans=[-1 1
-1 1];
3.- positions(shorts, :)= saves the given matrix in the given indexes. (NOTE!: only works if shorts is of type logical).
continuation of e.g.:
At this point, if you haven't omit anything, positions should be a 6x2 NaN matrix. the indexing will fill the true positions of shorts with the [-1 1] matrix. so after this, positions will be:
positions=[-1 1
NaN NaN
NaN NaN
NaN NaN
-1 1
NaN NaN]
Hope it helps

The MATLAB repmat function replicates and tiles the array. The syntax is
B = repmat(A,n)
where A is the input array and n specifies how to tile the array. If n is a vector [n1,n2] - as in your case - then A is replicated n1 times in rows and n2 times in columns. E.g.
A = [ 1 2 ; 3 4]
B = repmat(A,[2,3])
B = | |
1 2 1 2 1 2
3 4 3 4 3 4 __
1 2 1 2 1 2
3 4 3 4 3 4
(the lines are only to illustrate how A gets tiled)
In your case, repmat replicates the vector [-1, 1] for each non-zero element of shorts. You thus set each row of positions, whos corresponding entry in shorts is not zero, to [-1,1]. All other rows will stay NaN.
For example if
shorts = [1; 0; 1; 1; 0];
then your code will create
positions =
-1 1
NaN NaN
-1 1
-1 1
NaN NaN
I hope this helps you to clarify the effect of repmat. If not, feel free to ask.

Related

Finding whether the rows of a matrix in Matlab "fall" within the rows of another matrix

I have a matrix Ksets in Matlab with size Gx(l*N) and a matrix A with size MxN.
Each row of Ksets can be decomposed into l sub-rows with size 1xN.
Let me explain better with an example.
clear
N=3;
l=4;
G=2;
M=5;
Ksets=[1 2 3 5 6 7 9 10 11 0 0 0;
13 14 15 1 2 3 21 22 23 1 1 1]; %Gx(l*N)
A=[1 2 3;
5 6 7;
21 22 23;
1 2 3;
0 0 0]; %MxN
In the example:
row 1 of Ksets is composed of l sub-rows with size 1xN: [1 2 3], [5 6 7], [9 10 11], [0 0 0];
row 2 of Ksets is composed of l sub-rows with size 1xN: [13 14 15], [1 2 3], [21 22 23], [1 1 1].
I assume that each row of Ksets does not contain equal sub-rows.
I would like your help to construct a matrix Response with size GxM with Response(g,m)=1 if the row A(m,:) is equal to one of the l sub-rows of Ksets(g,:) and zero otherwise.
Continuing the example above
Response= [1 1 0 1 1;
1 0 1 1 0]; %GxM
This code does what I want:
Responsecorrectmy=zeros(G, M);
for x=1:G
for c=1:l
Responsecorrectmy(x,:)=Responsecorrectmy(x,:)+...
ismember(A,Ksets(x,(c-1)*N+1:c*N), 'rows').';
end
end
My code consists of 2 loops which is undesirable because in my real algorithm G,l are big. Do you have suggestions without loops?
It can be done with a little reshaping and dimension-permuting:
Response = permute(any(all(bsxfun(#eq, reshape(Ksets.', N, [], G), permute(A, [2 3 4 1])), 1), 2), [3 4 1 2]);
This works as follows:
reshape(Ksets.', N, [], G) reshapes Ksets into an N×l×G 3D-array so that each subrow is now separated from the others.
bsxfun(#eq, ..., permute(A, [2 3 4 1])) creates an N×l×G×M 4D-array with the result of comparing each element of the 3D-array from step 1 with each value in A.
all(..., 1) tests if all the elements of each subrow (i.e. first dimension) match. any(...,2) tests if this happens for any subrow of one of the original rows (i.e. second dimension).
permute(..., [3 4 1 2]) removes the first two dimensions (which became singleton in step 3), giving the desired G×M result. (It would not be safe to use squeeze for this because it would incorrectly remove the third dimension if G=1).
It's quite hard to do this vectorized, especially if the subsets you're trying to compare to are embedded in each row. What can be done for efficiency is to change the Ksets into a 3D matrix where each slice contains those subsets formatted into a 2D matrix where each subset is on a per-row basis. You can then use ismember combined with using just one loop on each row individually and populate your results.
Ksets2 = permute(reshape(Ksets.', [N l G]), [2 1 3]);
Response = false(G, M);
for i = 1 : G
Response(i, :) = ismember(A, Ksets2(:,:,i), 'rows')';
end
The first statement reshapes your data so that it becomes a 3D matrix, but because of MATLAB's column major processing, and because your subsets are in row major, we have to transpose the data prior to reshaping. However, this results in each column being in a subset, so we have to transpose each slice independently with the permute operation.
Once that's done, we allocate a matrix of the desired size, then loop through each row in Ksets (now transformed into rows of subsets) to produce the desired result.
We get:
>> Response
Response =
2×5 logical array
1 1 0 1 1
1 0 1 1 0

Making Tridiagonal matrix in matlab

I want to make a triadiagonal matrix with matlab, using
full(gallery('tridiag', 10, 1, -4, 6, -4, 1))
and i take that i have too many arguments in the function. Is there another way to do this?
I am trying to make the following matrix:
6 -4 1 0 0
-4 6 -4 1 0
1 -4 6 -4 1
0 1 -4 6 -4
0 0 1 -4 6
Since your matrix is pentadiagonal, I think the best solution is to use spdiags:
>> n = 5;
>> full(spdiags(ones(n,1)*[1,-4,6,-4,1],[-2,-1,0,1,2],n,n));
ans =
6 -4 1 0 0
-4 6 -4 1 0
1 -4 6 -4 1
0 1 -4 6 -4
0 0 1 -4 6
The full is optional and not recommended for large n.
Since there are 5 non-zero diagonals this is not a tridiagonal matrix so you cannot use the tridiag option. You have to manually generate such matrix by means of the diag() function, which allows you to create a matrix with a given diagonal and you can as well select which diagonal you want to write.
You can achieve this therefore by creating 5 different matrices, each of them will have a given non-zero diagonal:
n=5;
B=diag(6*ones(n,1),0)+diag(-4*ones(n-1,1),1)+diag(-4*ones(n-1,1),-1)+diag(1*ones(n-2,1),2)+diag(1*ones(n-2,1),-2);
In this code n=5 is the order of your matrix, then diag(6*ones(n,1),0) will create a vector (length n) with all 6 and such vector will be placed in the 0-th diagonal. Such matrix will have zero elsewhere.
Similarly diag(-4*ones(n-1,1),1) will create a vector (length n-1) with all -4 and such vector will be placed in the 1st superdiagonal. Such matrix will have zero elsewhere and we sum such matrix to the previous one.
And such "chain reaction" goes on until the matrix is fully generated.
Update: I've been looking around the gallery() help and there is indeed an option for a Toeplitz pentadiagonal. You might want to use then
full(gallery('toeppen',5,1,-4,6,-4,1))
I agree that for your huge case a sparse-based solution such as that of Troy Haskin is best. However, it's worth noting that you're precisely constructing a Toeplitz matrix (as Alessiox hinted), and you can use the built-in toeplitz() to do that. All that is needed is to figure out the number of zeros needed for padding the input nonzero elements of the first row and column (this is necessary since toeplitz asserts the size of the matrix to construct from the dimensions of the input vector):
n = 5; %// linear size of result
v = [1,-4,6,-4,1]; %// nonzero diagonal elements symmetrically
mid = ceil(length(v)/2); %// index of diagonal in the input vector
zerosvec = zeros(1,n-mid); %// zeros for padding the rest
colvec = [v(mid:-1:1), zerosvec]; %// first column of the result
rowvec = [v(mid:end), zerosvec]; %// first row of the result
toeplitz(colvec,rowvec) %// toeplitz does the heavy lifting

Reshape a matrix in matlab with nan elements

I have a Nx3-matrix in matlab, where I have a degree value from 0 to 360 in the first column, a radius value from 0 to 0.5 in the second and an integer in the third. Every combination out of (M(n,1),M(n,2)) is unique with M the matrix and n a random number between 1 and N, but it is possible that there is a value in M(:,1) or M(:,2) more than once. M is sorted, first after the first row, then after the second.
My target is now to reshape this matrix into a 360xV-matrix, with V the amount of unique values in M(:,2). If there is a value in M(:,3) at the position M(o,1) and M(p,2) with 1 <= o, p <= N, it should be placed at the position (o,p), if there is no value, then there should a NaN-value placed instead.
Is there a simple way to do this, or do I have to write my own function for that?
Edit:
Desired input:
0 0.25 1
0 0.43 4
1 0.25 2
2 0.03 5
2 0.43 2
Desired output:
NaN 1 4
NaN 2 NaN
5 NaN 2
You can use an approach of finding unique indices for the first and second columns from the input arrays and then using those to set elements in an appropriately (discussed in more detail inside the code as comments) sized output array with the elements from the third column. Here's the implementation -
%// Input array
A = [
0 0.25 1
0 0.43 4
1 0.25 2
2 0.03 5
2 0.43 2 ]
%// Find unique indices for col-1,2
[~,~,idx1] = unique(A(:,1)) %// these would form the row indices of output
[~,~,idx2] = unique(A(:,2)) %// these would form the col indices of output
%// Decide the size of output array based on the "extents" of those indices
nrows = max(idx1)
ncols = max(idx2)
%// Initialize output array with NaNs
out = NaN(nrows,ncols)
%// Set the elements in output indexed by those indices to values from
%// col-3 of input array
out((idx2-1)*nrows + idx1) = A(:,3)
Code run -
out =
NaN 1 4
NaN 2 NaN
5 NaN 2
Is there a simple way to do this, or do I have to write my own function for that?
You'll need to write a method, seeing that what you've described is utterly specific to your problem. There's methods to find unique values, so this will help you when designing your for loop.

Getting row and column numbers of valid elements in a matrix

I have a 3x3 matrix, populated with NaN and values of a variable:
NaN 7 NaN
5 NaN 0
NaN NaN 4
matrix = [NaN 7 NaN; 5 NaN 0; NaN NaN 4]
I would like to get the row and column numbers of non-NaN cells and put them in a matrix together with the value of the variable. That is, I would like to obtain the following matrix:
row col value
1 2 7
2 1 5
2 3 0
3 3 4
want = [1 2 7; 2 1 5; 2 3 0; 3 3 4]
Any help would be highly appreciated.
This can be done without loops:
[jj, ii, kk] = find((~isnan(matrix).*(reshape(1:numel(matrix), size(matrix)))).');
result = [ii jj matrix(kk)];
The trick is to multiply ~isnan(matrix) by a matrix of indices so that the third output of find gives the linear index of non-NaN entries. The transpose is needed to have the same order as in the question.
The following should work!
[p,q]=find(~isnan(matrix)) % Loops through matrix to find indices
want = zeros(numel(p),3) % three columns you need with same number of rows as p
for i=1:numel(p)
want[i,:] = [p(i) q(i) matrix(p(i), matrix(i))]
end
Should give you the correct result which is:
2 1 5
1 2 7
2 3 0
3 3 4
If you don't mind the ordering of the rows, you can use a simplified version of Luis Mendo's answer:
[row, col] = find(~isnan(matrix));
result = [row(:), col(:), matrix(~isnan(matrix))];
Which will result in:
2 1 5
1 2 7
2 3 0
3 3 4

Find row-wise minima in sparse matrix

I would like to get the minimum nonzero values per row in a sparse matrix. Solutions I found for dense matrices suggested masking out the zero values by setting them to NaN or Inf. However, this obviously doesn't work for sparse matrices.
Ideally, I should get a column vector of all the row-wise minima, as I would get with
minValues = min( A, [], 2);
Except, obviously, using min leaves me with an all-zeros column vector due to the sparsity. Is there a solution using find?
This is perfect for accumarray. Consider the following sparse matrix,
vals = [3 1 1 9 7 4 10 1]; % got this from randi(10,1,8)
S = sparse([1 3 4 4 5 5 7 9],[2 2 3 6 7 8 8 11],vals);
Get the minimum value for each row, assuming 0 for empty elements:
[ii,jj] = find(S);
rowMinVals = accumarray(ii,nonzeros(S),[],#min)
Note that rows 4 and 5 of rowMinVals, which are the only two rows of S with multiple nonzero values are equal to the min of the row:
rowMinVals =
3
0
1
1 % min([1 9]
4 % min([7 4]
0
10
0
1
If the last row(s) of your sparse matrix do not contain any non-zeros, but you want your min row value output to reflect that you have numRows, for example, change theaccumarray command as follows,
rowMinVals = accumarray(ii,nonzeros(S),[numRows 1],#min).
Also, perhaps you also want to avoid including the default 0 in the output. One way to handle that is to set the fillval input argument to NaN:
rowMinVals = accumarray(ii,nonzeros(S),[numRows 1],#min,NaN)
rowMinVals =
3
NaN
1
1
4
NaN
10
NaN
1
NaN
NaN
NaN
Or you can keep using a sparse matrix with the fifth input argument, issparse:
>> rowMinVals = accumarray(ii,nonzeros(S),[],#min,[],true)
rowMinVals =
(1,1) 3
(3,1) 1
(4,1) 1
(5,1) 4
(7,1) 10
(9,1) 1