I've a problem to find common elements between all columns of a matrix in MATLAB, I've tried to solve it my self, the basic problem is intersect function set intersect just between two matrices, so I wrote a code like this
A=randi(n,m);
B=struct();
for k=1:size(A,2)-1
B.(['b' num2str(k)])=intersect(A(:,k),A(:,k+1));
end
unfortunately the problem isn't solve cause the dimension of A is unknown so we have same problem with B!
thanks all.
One vectorized approach using bsxfun -
unqA = unique(A)
out = unqA(all(any(bsxfun(#eq,A,permute(unqA,[2,3,1])),1),2))
Sample run -
A =
8 5 6 4 8
4 6 7 5 9
9 4 4 7 5
9 4 9 5 6
9 9 7 9 6
9 5 9 4 8
8 5 6 9 8
7 5 6 7 4
out =
4
9
Related
I currently have a 3 by 3 matrix "m":
1 2 3
4 5 6
7 8 9
I would like to add a row to matrix 'm' to have a resultant matrix of:
1 2 3
4 5 6
7 8 9
10 11 12
A matrix in q is just a list of lists where inner lists represent rows.
m: ((1 2 3);(4 5 6);(7 8 9))
In order to add one more row all you have to do is add one more inner list to it:
m: m,enlist 10 11 12
enlist is important here, without it you'll end up with this:
q)((1 2 3);(4 5 6);(7 8 9)),10 11 12
1 2 3
4 5 6
7 8 9
10
11
12
I agree; using 0N!x to view the structure is very useful.
To achieve what you want then you can simply do;
q)show m:3 cut 1+til 9 /create matrix
1 2 3
4 5 6
7 8 9
q)show m,:10 11 12 /join new 'row'
1 2 3
4 5 6
7 8 9
10 11 12
q)
I have a vector V periodic an I want to write a program which associates to each period the set of different elements in that period and gives its cardinal.
For example:
For the vector v=(2 3 7 2 7 3 2 3 7 2 7 3) and cardinal 6, give me only the vector P=(2 3 7 2 7 3).
For The vector v=(2 3 7 5 8 6 10 11 10 6 8 5 7 3 2 3 7 5 8 6) and the cardinal 14, give me P=(2 3 7 5 8 6 10 11 10 6 8 5 7 3).
If I understood you correctly you have to use build-in function seqperiod(v).
In your case, for example:
v=[2 3 7 5 8 6 10 11 10 6 8 5 7 3 2 3 7 5 8 6];
>> seqperiod(v)
ans =
14
Interesting moment: in your second example there aren't full repetition. So we can't really say is it periodic... But seqperiod still works and returns 14 as you wish.
go further you can use it in this way:
[p, num] = seqperiod(v);
p = 14
num = 1.4286
num - is a number of repetitions.
Ok. Now you say you need not only the cardinal, but the vector. So you can do it easily:
result = v(1:p);
Hope it helps!
I have a 3D matrix and I want to store each 2D component of this in the row of another 2D matrix which has many rows as the 3rd dimension of the 3D matrix.
How can I do this?
With permute & reshape -
reshape(permute(A,[3 2 1]),size(A,3),[])
Sample run -
>> A
A(:,:,1) =
7 1 7 5
3 4 8 5
9 4 2 6
A(:,:,2) =
7 7 2 4
7 6 5 6
3 2 9 3
A(:,:,3) =
7 7 5 3
3 9 2 8
5 9 2 3
>> reshape(permute(A,[3 2 1]),size(A,3),[])
ans =
7 1 7 5 3 4 8 5 9 4 2 6
7 7 2 4 7 6 5 6 3 2 9 3
7 7 5 3 3 9 2 8 5 9 2 3
If you don't mind a little indexing madness...
You can build a linear index with the appropriate shape, which applied on the original array will give the desired result:
B = A(bsxfun(#plus, (1:L*M:L*M*N).', reshape(bsxfun(#plus, (0:L:L*M-1).', 0:L-1),1,[])));
Example:
>> A = randi(10,2,3,4)-1; %// example array; size 2x3x4
>> A
A(:,:,1) =
5 3 2
9 8 9
A(:,:,2) =
8 7 4
9 8 6
A(:,:,3) =
3 4 8
0 4 4
A(:,:,4) =
2 8 8
4 6 7
Result:
>> B
B =
5 3 2 9 8 9
8 7 4 9 8 6
3 4 8 0 4 4
2 8 8 4 6 7
That is easily done with MATLABs matrix unrolling syntax:
A=ones(N,M,O);
B=zeros(O,N*M);
for ii=1:size(A,3)
aux=A(:,:,ii); % aux is NxM
B(ii,:)=aux(:); % unroll!
end
(note I called O the thing you call N in your pictures)
Anybody know a fast way to produce a matrix consisting of a linspace for each row? For example, the sort of pattern I'm looking for in this matrix is:
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
...
1 2 3 4 5 6 7 8 9 10
Anyone know any fast tricks to produce this WITHOUT using a for loop?
I just figured this out, so just in case anyone else was troubled by this, we can achieve this exact pattern by:
a=linspace(1,10,10);
b=ones(3,1)*a;
This will give:
>> a = 1 2 3 4 5 6 7 8 9 10
>> b = 1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You need to use repmat.
Example:
>> B = repmat(1:10,[3 1])
B =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
You can vary the value of 3 there. You can change it accordingly.
Another shortcut I can recommend is similar to repmat, but you specify a base array first of a = 1:10;. Once you do this, you specify a series of 1s in the first dimension when indexing which should produce a matrix of the same vectors with many rows as you want, where each row consists of the base array a. As such:
%// number of times to replicate
n = 4;
a = 1:10;
a = a(ones(1,n),:);
Result:
a =
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
1 2 3 4 5 6 7 8 9 10
Insert this command: transpose(ndgrid(1:10,1:n));, where n is the number of rows desired in the result.
You can consider these solutions:
With basic matrix indexing (taken from here)
b=a([1:size(a,1)]' * ones(1,NumToReplicate), :) %row-wise replication
b=a(:, ones(NumToReplicate, 1)) %column-wise replication
With bsxfun:
bsxfun(#times,a,(ones(1,NumToReplicate))') %row-wise replication
bsxfun(#times,a',(ones(1,NumToReplicate))) %column-wise replication
You are welcome to benchmark above two solutions with repmat.
I have random matrix(A) and I find a result I'd like to use later for my code
A=randint(5,7,[1,9])
ans A =
8 1 2 2 6 7 7
9 3 9 4 1 7 1
2 5 9 9 8 4 3
9 9 5 8 9 6 1
6 9 8 9 7 2 1
How can I now get:
A = [8,1,2,2,6,7,7;9,3,9...7,2,1];
without having to type it myself.
MATLAB has a function for that: MAT2STR
>> A = randi([1,9],[5,7]);
>> mat2str(A)
ans =
[5 5 7 5 3 2 5;5 6 5 3 8 4 1;9 8 8 1 7 9 6;1 5 5 1 8 6 3;3 4 5 8 9 9 5]
This is suitable for use with EVAL
Just thought of another way. Your goal is to have A in your script - right?
You can just paste it as follows:
A = [
8 1 2 2 6 7 7
9 3 9 4 1 7 1
2 5 9 9 8 4 3
9 9 5 8 9 6 1
6 9 8 9 7 2 1
]
(note the square brackets)
It will evaluate to your original matrix.
Make the string yourself:
Str = ['[' sprintf('%i',A(1)) sprintf(',%i',A(2:end)) ']']
Note this string does not contain any ; as in your example. so when you evaluate it you will get a 1x35 vector (instead of the original 5x7matrix)
So easiest way to fix this would be to add after you evaluate the string.
A = reshape(A,5,7)
It will look like
B = [....
B = reshape(B,5,7)