Split array into pieces in MATLAB - matlab

I woutld like to split an array into equal pieces like this:
a=[1 2 3 4 5 6 7 8 9 10]
n = 2;
b = split(a, n);
b =
1 2 3 4 5
6 7 8 9 10
Which function can do this?

Try this:
a = [1 2 3 4 5 6]
reshape (a, 2, 3)

If a can be divided by n you can actually provide only one argument to RESHAPE.
To reshape to 2 rows:
b = reshape(a,2,[])
To reshape to 2 columns:
b = reshape(a,[],2)
Note that reshape works by columns, it fills the 1st column first, then 2nd, and so on. To get the desired output you have to reshape into 2 columns and then transpose the result.
b = reshape(a,[],2)'
You can place a check before reshape:
assert(mod(numel(a),n)==0,'a does not divide to n')

Related

Without for loop, can I generate list [1 2 3 2 3 4 3 4 5 ...] in matlab?

Unlike Python, MATLAB list generation expression is limited. In MATLAB I am only allowed to do a:b:c. Can I generate a list [1 2 3 2 3 4 3 4 5 ...] in MATLAB without using for loop?
N = 3;
M = 4;
result = reshape((1:N).'+(0:M-1), 1, []);
gives
result =
1 2 3 2 3 4 3 4 5 4 5 6
How it works
(1:N).'+(0:M-1) uses implicit expansion to create the M×N matrix
1 2 3 ... M
2 3 4 ... M+1
3 4 5 ... M+2
...
N N+1 N+2 ... N+M-1
Then reshape(..., 1, []) reshapes this matrix into a row vector, reading the elements in column-major order (down, then across).
One approach would be to make three lists [1,2,3...], [2,3,4...] and [3,4,5...] and interleave them. Alternatively, you can take advantage of the pattern: [1,2,3,4,5,6,7,8,9]-[0,0,0,2,2,2,4,4,4]=[1,2,3,2,3,4,3,4,5]. The repelem() function is useful for this kind of operation.
You can try cell2mat + arrayfun like belwn
n = 3;
m = 3;
res = cell2mat(arrayfun(#(x) x+(1:n),1:m,'UniformOutput',false));
such that
res =
2 3 4 3 4 5 4 5 6

How do I extract the odd and even rows of my matrix into two separate matrices in scilab?

I'm very new to scilab syntax and can't seem to find a way to extract the even and odd elements of a matrix into two separate matrix, suppose there's a matrix a:
a=[1,2,3,4,5,6,7,8,9]
How do I make two other matrix b and c which will be like
b=[2 4 6 8] and c=[1 3 5 7 9]
You can separate the matrix by calling row and column indices:
a=[1,2,3,4,5,6,7,8,9];
b=a(2:2:end);
c=a(1:2:end);
[2:2:end] means [2,4,6,...length(a)] and [1:2:end]=[1,3,5,...length(a)]. So you can use this tip for every matrix for example if you have a matrix a=[5,4,3,2,1] and you want to obtain the first three elements:
a=[5,4,3,2,1];
b=a(1:1:3)
b=
1 2 3
% OR YOU CAN USE
b=a(1:3)
If you need elements 3 to 5:
a=[5,4,3,2,1];
b=a(3:5)
b=
3 2 1
if you want to elements 5 to 1, i.e. in reverse:
a=[5,4,3,2,1];
b=a(5:-1:1);
b=
1 2 3 4 5
a=[1,2,3,4,5,6,7,8,9];
b = a(mod(a,2)==0);
c = a(mod(a,2)==1);
b =
2 4 6 8
c =
1 3 5 7 9
Use mod to check whether the number is divisible by 2 or not (i.e. is it even) and use that as a logical index into a.
The title is about selecting rows of a matrix, while the body of the question is about elements of a vector ...
With Scilab, for rows just do
a = [1,2,3 ; 4,5,6 ; 7,8,9];
odd = a(1:2:$, :);
even = a(2:2:$, :);
Example:
--> a = [
5 4 6
3 6 5
3 5 4
7 0 7
8 7 2 ];
--> a(1:2:$, :)
ans =
5 4 6
3 5 4
8 7 2
--> a(2:2:$, :)
ans =
3 6 5
7 0 7

Matlab - find function between matrix and cell array

I’ve a matrix A = (4*4) and a cell array B {4,1}. I’d like to find all the values of B in A, searching row by row and after I’d like to delete the correspondent column associated to this particular value. I’ve a problem using bsxfun o cellfun and find function with a matrix and a cell array. I‘ve tried to convert the cell array into a matrix but I don’t have more the exact correspondence.
For example:
A =
1 5 10 23
2 4 2 18
3 3 5 14
1 9 10 4
B =
1
2 4
3 3 14
1
To obtain:
C =
10
2
5
10
Thanks in advance,
L.
Here's how:
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
C = A(:, all(~vertcat(C{:})));
The cellfun is fed with two cell arrays: the first one contains the rows of A and second one is B. The anonymous function is the tricky part; it operates on a pair of two corresponding rows as follows:
It employs ismember to check which columns in A contain any of the elements in B.
It uses find to pick only the first N ones, with respect to the number of elements in the B.
It uses sparse as a fancy way of zeroing out the rest of the elements.
For your example it would look like this:
A = [1 5 10 23; 2 4 2 18; 3 3 5 14; 1 9 10 4];
B = {1; [2 4]; [3 3 14]; 1};
C = cellfun(#(x, y){sparse(1,find(ismember(x,y),numel(y)),true,1,size(A,2))}, ...
mat2cell(A, ones(size(A, 1), 1), size(A, 2)), B(:));
which yields:
C =
{
[1 0 0 0]
[1 1 0 0]
[1 1 0 1]
[1 0 0 0]
}
After that, it's a simple matter of logical indexing to pick the resulting columns:
C = A(:, all(~vertcat(C{:})));
which in this case should be:
C =
10
2
5
10

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.

Generate a vector with elements that contain a fixed number of unique values

Suppose I have a vector
A =
3 5 3 3 2 2 4 2 6
I need to produce a new vector B that will contain all these values from the beggining vector A that will result in a unique number of n elements (suppose n=3, for the purpose of this example). The new vector should be B =
3 5 3 3 2
since up to the fifth element of vector A we have 3 unique values(3,5,2).
Actual vectors are a lot larger, so I would rather need a general solution and preferably by avoiding a loop. Any ideas? Thanks in advance
You can use unique for this problem. However, be sure to use the 'stable' option.
A = [3 5 3 3 2 2 4 2 6];
n = 3;
[x, id] = unique(A,'stable');
B = A(1:id(3))
This results in
B =
3 5 3 3 2
Do the following:
A = [3 5 3 3 2 2 4 2 6];
n = 3;
[b,i] = unique(A,'first');
h = sort(i);
A(1:h(n))