Lets say,we've the following two vectors:
data = [1 2 2 2 3 3 3 3 3 3 4 4 4 4 4 ];
x_axis = [1 1 1 2 2 2 3 3 3 3 3 4 4 5 5 ];
What i now want to have is to count all data values which are for example one in the x_axis ,then these values which are two etc. So the result should look like as following (which i then can represent as a histogram):
result=[5 8 16 8 8];
x_axis=[1 2 3 4 5];
This is the perfect application example for accumarray:
data = [1 2 2 2 3 3 3 3 3 3 4 4 4 4 4 ];
x_axis = [1 1 1 2 2 2 3 3 3 3 3 4 4 5 5 ];
result = accumarray(x_axis(:),data(:),[],#sum)
result =
5
8
16
8
8
Related
This question already has answers here:
Replicate matrix one row at a time [duplicate]
(2 answers)
Closed 6 years ago.
I need to enlarge a matrix A to a matrix B with size n times the size of A. The values must be repeated, eg:
A size 2x3, n = 3, leads to B size 6x9:
Sample values:
A =
1 2 3
4 5 6
Results with:
B =
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
What is the fastest way to achieve that in Matlab?
There is also the Kronecker Tensor Product (kron) function:
n = 3;
B = kron(A,ones(n));
B =
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
1 1 1 2 2 2 3 3 3
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
4 4 4 5 5 5 6 6 6
If you have the Image Processing Toolbox you can easily do this using imresize with nearest neighbor interpolation.
A = [1 2 3; 4 5 6];
% Repeat each element 3 times in each direction
B = imresize(A, 3, 'nearest');
% 1 1 1 2 2 2 3 3 3
% 1 1 1 2 2 2 3 3 3
% 1 1 1 2 2 2 3 3 3
% 4 4 4 5 5 5 6 6 6
% 4 4 4 5 5 5 6 6 6
% 4 4 4 5 5 5 6 6 6
If you don't have the Image Processing Toolbox, you can use interp2 with nearest neighbor interpolation to do something similar.
scaleFactor = 3;
[xx,yy] = meshgrid(linspace(1, size(A, 2), size(A, 2) * scaleFactor), ...
linspace(1, size(A, 1), size(A, 1) * scaleFactor));
B = interp2(A, xx, yy, 'nearest');
Given any number. Lets say for example 5, I need to generate a matrix similar to this:
1 2 3 4 5
2 2 3 4 5
3 3 3 4 5
4 4 4 4 5
5 5 5 5 5
How to generate a matrix similar to this using Matlab?
I'd use bsxfun:
n = 5;
matrix = bsxfun(#max, 1:n, (1:n).');
An alternative (probably slower) is to use ndgrid:
n = 5;
[ii, jj] = ndgrid(1:n);
matrix = max(ii, jj);
Nothing will ever beat bsxfun as used by Luis Mendo., but for the sake of reminding people of the existence of Matlab's gallery function, here another approach:
n = 5;
A = gallery('minij',n)
B = n + 1 - A(end:-1:1,end:-1:1)
A =
1 1 1 1 1
1 2 2 2 2
1 2 3 3 3
1 2 3 4 4
1 2 3 4 5
B =
1 2 3 4 5
2 2 3 4 5
3 3 3 4 5
4 4 4 4 5
5 5 5 5 5
I have some matrix :
A = [ 1 2 3 4 5 6;
1 2 3 4 5 6]
B = [ 6 5 4 3 2 1;
6 5 4 3 2 1]
C = [ 1 2 3 4 5 6;
1 2 3 4 5 6]
what is code to make this following matrix:
Result = [1 2 9 9 10 11 5 5 5 6;
1 2 9 9 10 11 5 5 5 6]
Note : Actually the above matrix is sum of 3 matrix above which had been already rearranged like as the following matrix. #sum is sum which is based on column.
1 2 3 4 5 6
1 2 3 4 5 6
6 5 4 3 2 1
6 5 4 3 2 1
1 2 3 4 5 6
1 2 3 4 5 6
And. I sum first row by first row, and second row by second row.
To do what you say above:
Result = zeros(size(A) + [0,4]);
Result(:,1:size(A,2)) = A;
Result(:,3:end-2) = Result(:,3:end-2) + B;
Result(:,5:end) = Result(:, 5:end) + C;
The point is, you can select a subregion of a matrix, and assign another matrix to it. You just have to make sure both sides of the assignment are the same shape.
in MATLAB I have a cell array like this
a = { 1 2 2 3 4 5 [] []
2 4 5 4 3 2 4 5
4 5 4 3 4 [] [] []}
I want to remove empty elements in a way that I get this :
a = { 1 2 2 3 4 5 2 4 5 4 3 2 4 5 4 5 4 3 4}
but when I use this : a(cellfun(#isempty,a)) = [];
what I get is this :
a = {1 2 4 2 4 5 2 5 4 3 4 3 4 3 4 5 2 4 5}
which is not what I want
The problem is that the linear index runs in the direction of rows, i.e. it runs through the first conlumn, then through the second column etc.
You can see this when you call reshape on a vector:
>> reshape([1 2 3 4 5 6 7 8 9],3,3)
ans =
1 4 7
2 5 8
3 6 9
To achieve the result you want, you need to transpose a before indexing into it.
a = a';
a(cellfun(#isempty,a)) = [];
You can try this :
A(~cellfun('isempty',A))
For a matrix A (4 rows, 1000 columns). I want to group the columns of the matrix A which have the same value for the third line. so I must have sub matrix with a third row that contains the same value.
for example:
if:
A =
1 4 5 2 2 2 2 1 1 5
1 4 5 4 4 2 2 4 5 2
3 3 3 3 4 1 3 5 3 4
4 5 5 5 4 1 5 5 5 5
then
A1 =
1 4 5 2 2 1
1 4 5 4 2 5
3 3 3 3 3 3
4 5 5 5 5 5
A2 =
2 5
4 2
4 4
4 5
A3 =
2
2
1
1
the result can be in the form of a cell.
here's one possible hack (warning: I haven't been able to check this):
A =
1 4 5 2 2 2 2 1 1 5
1 4 5 4 4 2 2 4 5 2
3 3 3 3 4 1 3 5 3 4
4 5 5 5 4 1 5 5 5 5
specialRow=3;
unqCols = unique(A(specialRow,:));
numUnq = length(unqCols);
sepMats{numUnq}=[];
for i=1:numUnq
sepMats{i} = A(:,A(specialRow,:)==unqCols(i));
end
In the example you shown, there are 4 unique elements in the 3rd row, so you should obtain 4 submatrices, but you only show 3 ?
Here is one way:
clear all;
%data
A = [1 4 5 2 2 2 2 1 1 5;
1 4 5 4 4 2 2 4 5 2;
3 3 3 3 4 1 3 5 3 4;
4 5 5 5 4 1 5 5 5 5
]
%engine
row = 3;
b = unique(A(row,:));
r = arrayfun(#(i) A(:,A(row,:)==b(i)),1:length(b), 'UniformOutput',false);
r{:}
You can make the assignment in a single line using ACCUMARRAY:
A = [1 4 5 2 2 2 2 1 1 5;
1 4 5 4 4 2 2 4 5 2;
3 3 3 3 4 1 3 5 3 4;
4 5 5 5 4 1 5 5 5 5
];
out = accumarray(A(3,:)', (1:size(A,2)), [], #(x){A(:,x)} );
With this, out{i} contains all columns of A where the third row of A equals i (and empty in case there is no valid column).
If you want out{i} to contain columns corresponding to the i-th smallest unique value in the third row of A, you can use GRP2IDX from the statistics toolbox first:
[idx,correspondingEntryInA] = grp2idx(A(3,:)'); %'#
out = accumarray(idx, (1:size(A,2)), [], #(x){A(:,x)} );
Here, out{i} contains the columns corresponding to correspondingEntryInA(i).