how to replicate an array - arrays

I want to make a function like this
>> matdup([1 2],3,4) %or any other input that user wish to enter
ans=
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
I am stuck in my code. My logic:
m = matdup(input,row,col)
for i = 1:row
for j = 1:col
m(i, j)= input;
This is producing this:
>> matdup(1,2,2)
ans=
1 1
1 1
But failed at this:
>> matdup([1 2],3,4)
error at console:
Subscripted assignment dimension mismatch.
Error in ==> matdup at 6
m(i, j)= input
Any idea?

Method 1: Are you allowed to use ones? Try this -
A = [1 2]
rowIdx = [1 : size(A,1)]';
colIdx = [1 : size(A,2)]';
out = A(rowIdx(:, ones(3,1)), colIdx(:, ones(4,1)))
Output
out =
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
1 2 1 2 1 2 1 2
Method 2: Are you allowed to use bsxfun and permute? Try this for the same result -
A = [1 2]
row_mapped = bsxfun(#plus,A,zeros(3,1))
out = reshape(bsxfun(#plus,row_mapped,permute(zeros(4,1),[3 2 1])),[3 8])

Matlab has a funcion called repmat that does the same.
If you want to create a similar function, you could do something like this:
function B = matdup(A, M, N)
[nr, nc] = size(A);
B = zeros([nr nc] .* [M N]);
for r = 1:M
for c = 1:N
rr = (r - 1) * nr + 1;
cc = (c - 1) * nc + 1;
B(rr:rr + nr - 1, cc:cc + nc - 1) = A;
end
end
end
Note this function is restricted to 2D matrices.

Try kron:
matdup = #(x,m,n) kron(ones(m,n),x)
Demonstration:
>> A = [5 6 7];
>> out = matdup(A,3,2)
out =
5 6 7 5 6 7
5 6 7 5 6 7
5 6 7 5 6 7
Note that you can switch the inputs to kron to effectively replicate elements rather than the whole matrix:
repel = #(x,m,n) kron(x,ones(m,n));
Demonstration:
>> A = [5 6 7];
>> out = repel(A,3,2)
out =
5 5 6 6 7 7
5 5 6 6 7 7
5 5 6 6 7 7

The replication can be done easily using mod:
function R = matdup(A, M, N)
[m n]= size(A);
R = A(mod(0:m*M-1,m)+1, mod(0:n*N-1,n)+1)

Related

BetaCV in matlab

I have a matrix indices with 2 columns and 20 rows.
indices =
[1 2;
2 3;
2 1;
... ]
there is a second matrix distMat with 4 rows and 4 columns and i want to find the sum of elements in distMat located in position given in each row of indices[]
distMat =
[1 3 1 5
2 2 4 2
3 8 3 7
3 8 3 7]
since indices rows are 1 2, 2 3, 3 1 so elements of that positions should be retrieved and added
so i wrote
result = sum(distMat[indices])
I am getting syntax error. so how to solve this problem
Another approach: use sparse to build a logical index that selects the values to be summed:
indices = [1 2; 2 3; 2 1];
distMat = [1 3 1 5; 2 2 4 2; 3 8 3 7; 3 8 3 7];
result = sum(distMat((sparse(indices(:,1), indices(:,2), true, size(distMat,1), size(distMat,2)))));
This works in Octave as well.
One way would be to get the linear indices and then simply index and sum, just like you had at the end -
idx = sub2ind(size(distMat), indices(:,1), indices(:,2));
out = sum(distMat(idx))
Sample run -
>> indices
indices =
1 2
2 3
2 1
>> distMat
distMat =
1 3 1 5
2 2 4 2
3 8 3 7
3 8 3 7
>> idx = sub2ind(size(distMat), indices(:,1), indices(:,2));
>> distMat(idx)
ans =
3
4
2
>> sum(distMat(idx))
ans =
9

Extract pattern and subsequent n elements from array and count number of occurences

I have an array of doubles like this:
C = [1 2 3 4 0 3 2 5 6 7 1 2 3 4 150 30]
i want to find the pattern [1 2 3 4] within the array and then store the 2 values after that pattern with it like:
A = [1 2 3 4 0 3]
B = [1 2 3 4 150 30]
i can find the pattern like this but i don't know how to get and store 2 values after that with the previous one.
And after finding A, B if i want to find the number of occurrences of each arrays within array C how can i do that?
indices = cellfun(#(c) strfind(c,pattern), C, 'UniformOutput', false);
Thanks!
Assuming you're fine with a cell array output, this works fine:
C = [1 2 3 4 0 3 2 5 6 7 1 2 3 4 150 30 42 1 2 3 4 0 3]
p = [1 2 3 4]
n = 2
% full patttern length - 1
dn = numel(p) + n - 1
%// find indices
ind = strfind(C,p)
%// pre check if pattern at end of array
if ind(end)+ dn > numel(C), k = -1; else k = 0; end
%// extracting
temp = arrayfun(#(x) C(x:x+dn), ind(1:end+k) , 'uni', 0)
%// post processing
[out, ~, idx] = unique(vertcat(temp{:}),'rows','stable')
occ = histcounts(idx).'
If the array C ends with at least n elements after the last occurrence of the pattern p, you can use the short form:
out = arrayfun(#(x) C(x:x+n+numel(p)-1), strfind(C,p) , 'uni', 0)
out =
1 2 3 4 0 3
1 2 3 4 150 30
occ =
2
1
A simple solution can be:
C = [1 2 3 4 0 3 2 5 6 7 1 2 3 4 150 30];
pattern = [1 2 3 4];
numberOfAddition = 2;
outputs = zeros(length(A),length(pattern)+ numberOfAddition); % preallocation
numberOfFoundPattern = 1;
lengthOfConsider = length(C) - length(pattern) - numberOfAddition;
for i = 1:lengthOfConsider
if(sum(C(i:i+length(pattern)) - pattern) == 0) % find pattern
outputs(numberOfFoundPattern,:) = C(i:i+length(pattern)+numberOfAddition);
numberOfFoundPattern = numberOfFoundPattern + 1;
end
end
outputs = outputs(1:numberOfFoundPattern - 1,:);

MATLAB: detect and remove mirror imaged pairs in 2 column matrix

I have a matrix
[1 2
3 6
7 1
2 1]
and would like to remove mirror imaged pairs..i.e. output would be either:
[1 2
3 6
7 1]
or
[3 6
7 1
2 1]
Is there a simple way to do this? I can imagine a complicated for loop, something like (or a version which wouldn't delete the original pair..only the duplicates):
for i=1:y
var1=(i,1);
var2=(i,2);
for i=1:y
if array(i,1)==var1 && array(i,2)==var2 | array(i,1)==var2 && array(i,2)==var1
array(i,1:2)=[];
end
end
end
thanks
How's this for simplicity -
A(~any(tril(squeeze(all(bsxfun(#eq,A,permute(fliplr(A),[3 2 1])),2))),2),:)
Playing code-golf? Well, here we go -
A(~any(tril(pdist2(A,fliplr(A))==0),2),:)
If dealing with two column matrices only, here's a simpler version of bsxfun -
M = bsxfun(#eq,A(:,1).',A(:,2)); %//'
out = A(~any(tril(M & M.'),2),:)
Sample run -
A =
1 2
3 6
7 1
6 5
6 3
2 1
3 4
>> A(~any(tril(squeeze(all(bsxfun(#eq,A,permute(fliplr(A),[3 2 1])),2))),2),:)
ans =
1 2
3 6
7 1
6 5
3 4
>> A(~any(tril(pdist2(A,fliplr(A))==0),2),:)
ans =
1 2
3 6
7 1
6 5
3 4
Here a not so fancy, but hopefully understandable and easy way.
% Example matrix
m = [1 2; 3 6 ; 7 1; 2 1; 0 3 ; 3 0];
Comparing m with its flipped version, the function ismember returns mirror_idx, a 1D-vector with each row containing the index of the mirror-row, or 0 if there's none.
[~, mirror_idx] = ismember(m,fliplr(m),'rows');
Go through the indices of the mirror-rows. If you find one "mirrored" row (mirror_idx > 0), set its counter-part to "not mirrored".
for ii = 1:length(mirror_idx)
if (mirror_idx(ii) > 0)
mirror_idx(mirror_idx(ii)) = 0;
end
end
Take only the rows that are marked as not having a mirror.
m_new = m(~mirror_idx,:);
Greetings

How to sort rows of a matrix based on frequency of the elements of one column?

I tried using sortrows function in Matlab. Is there any way using this function or any idea to sort rows of a matrix based on frequency of elements of a column of that matrix.
As an example: I have this matrix
matrix = [1 3 1;
1 4 2;
2 5 4;
3 2 3;
5 5 4;
5 3 3;
4 3 2;
4 2 3;
3 6 4;
2 4 3];
I would like to get something similar to this:
sorted_based_on_3rd_col = [2 4 3;
3 2 3;
4 2 3;
5 3 3;
2 5 4;
3 6 4;
5 5 4;
1 4 2;
4 3 2;
1 3 1]
which is sorted based most frequent element on third column.
Thanks for any help!
This is one way:
x = matrix(:,3);
[c,b] = histc(x,unique(x))
[~,idx] = sort(c(b),'descend')
out = matrix(idx,:)
If you don't care about the order of elements with equal frequency, this can be done like so:
>> freq = accumarray(matrix(:,3), 1);
>> [~, ind] = sort(freq(matrix(:, 3)), 1, 'descend'); % index that sorts matrix
>> matrix(ind, :) % reshuffle matrix to sort
ans =
3 2 3
5 3 3
4 2 3
2 4 3
2 5 4
5 5 4
3 6 4
1 4 2
4 3 2
1 3 1
If you do care, you need to pre-sort the matrix before anything else. Since matlab's sort is stable, this will preserve the order of items that are equal in the second sort.
>> matrix = sortrows(matrix, 1)
matrix =
1 3 1
1 4 2
2 5 4
2 4 3
3 2 3
3 6 4
4 3 2
4 2 3
5 5 4
5 3 3
>> freq = accumarray(matrix(:,3),1);
>> [~, ind] = sort(freq(matrix(:,3)), 1, 'descend');
>> matrix(ind, :)
ans =
2 4 3
3 2 3
4 2 3
5 3 3
2 5 4
3 6 4
5 5 4
1 4 2
4 3 2
1 3 1

Creating a 2D matrix in Matlab

I want to Create a matrix like
A = [1 2 3 ;4 5 6; 7 8 9];
I want to do it like this,
A = 1 + val : 1 : 3 + val ;
val = [0 3 6];
But I am only getting [1 2 3] , Not 2D matrix .
Try this,
val = [0 3 6];
A = bsxfun(#plus,val',1:3);
A =
1 2 3
4 5 6
7 8 9

Resources