Concatenate two arrays in MATLAB - matlab

I have a 5000x2 array as:
A = [1, 3; 2, 4; 1, 6; 2, 4; 1, 7];
I have another array of size 100x2 which looks as:
B = [1, 14; 2, 15];
How can I create a third array where I am going to use column 2 of vector B as follows to modify matrix A:
C = [1, 3, 14; 2, 4, 15; 1, 6, 14; 2, 4, 15; 1, 7, 14];
I am just trying to use column 1 of B as keys which would be same as contents of column 1 of A.

Assuming the first column on B is indices = 1 2 3 4 ..., the following should work:
A =
1 3
2 4
2 6
2 4
1 7
2 8
C(:,3) = B(A(:,1),2)
C =
1 3 14
2 4 15
2 6 15
2 4 15
1 7 14
2 8 15
or if you just want 14 15 14 15:
C = [A repmat(B(:,2),size(A,1)/size(B,1),1)]

Do the following:
A(A(:,1)== key ,3) = B(B(:,1)== key ,2);
where key takes the values of 1 and 2 (and any other possible key).
What does this line do? A(:,1)== key will be true on the rows where the first column values are equal to key, and then sets the third column of A equal to the values of B that have the same key.
You should execute this line for key=1 and key=2 in order to get what you need.

Related

Finding Positions of Repeating Elements in a Matrix in Matlab

I have a vector A = [ 1 1 1 2 3 3 3 2 2 1 1 1 1 3 3 3 ].
I want to find the positions of every element and store this in its own matrix.
To be more specific, I want to find the position of every elements for each set of elements, in a n by m matrix (where m would be the type of element, and n would be the number of elements found in vector A).
So, for example, assuming there are only values 1, 2, and 3 in vector A, the first column of my matrix would be for values that are 1, and would read off (1, 2, 3, 10, 11, 12, 13) and the second column, for values of 2, would read off (4, 8, 9) and the third column, for values of 3, would read off (5, 6, 7, 14, 15, 16).
This one liner works as expected:
B = accumarray(A', 1:length(A), [], #(x) {sort(x)})
B is a cell array where B{i} contains the sorted list of indices where i is located.
This could be one approach -
%// For each element create a pair: [R,C], where the first element R would
%// represent its index position in input array and C would be their uniqueness
[R,C] = find(bsxfun(#eq,A(:),unique(A(:).'))) %//'
%// Find lengths of each unique group
lens = diff([0 ; find(diff(C)) ; numel(C)])
%// Store each element into groups based on the uniqueness and whose
%// values would be the index positions i.e. taken from R
out = mat2cell(R(:).',1,lens)
Sample run for given input -
>> A
A =
1 1 1 2 3 3 3 2 2 ...
1 1 1 1 3 3 3
>> celldisp(out)
out{1} =
1 2 3 10 11 12 13
out{2} =
4 8 9
out{3} =
5 6 7 14 15 16
Similar to Divakar's answer but with sort
[out,i] = sort(A);
out1 = diff(find([1,diff(out)]));
out2 = [out1,numel(A)-sum(out1(:))];
out3 = mat2cell(i,1,out2);
Results:
A = [ 1 1 1 2 3 3 3 2 2 1 1 1 1 3 3 3 ]; %// input
>> celldisp(out3)
out3{1} =
1 2 3 10 11 12 13
out3{2} =
4 8 9
out3{3} =
5 6 7 14 15 16

Outer product in Matlab?

How to turn two vectors into a matrix of all combinations of their elements?
For example, vectors
>> A=[1;2;3]
A =
1
2
3
>> B=[4;5;6]
B =
4
5
6
Should be turned to
[1, 4; 1, 5; 1, 6; 2, 4; 2, 5; 2, 6; 3, 4; 3, 5; 3, 6]
ans =
1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6
I'm sure there is a simpler way of doing this but... meshgrid will get you close and you just need to perform some array manipulation to get your result:
[BA, BB] = meshgrid(A,B);
[BA(:) BB(:)]
An order of magnitude slower than meshgrid, but just to show you a different method:
[kron(A,ones(numel(B),1)), kron(ones(numel(A),1), B)];

Ranges with different step size for odd and even steps in MATLAB

What is the fastest and the simplest way to generate an array like
[0, 1, 3, 4, 6, 7, 9, 10, ...]
in MATLAB?
You can obtain the cumulative sum of the vector of steps (in your case it is [1 2 1 2 1 2 1 2 ...]). For example:
x = cumsum([0, repmat([1 2], 1, 4)])
x =
0 1 3 4 6 7 9 10 12
You can generate matrix with two rows: top row for odd array elements, bottom row for even elements. Than transform matrix into array with reshape.
>> a=[0:3:15; 1:3:16]
a =
0 3 6 9 12 15
1 4 7 10 13 16
>> a=reshape(a,1,12)
a =
0 1 3 4 6 7 9 10 12 13 15 16
Not one line but will work for either an odd or even number of total elements, and could be expanded if you wanted more than two different steps:
a = zeros(1,8);
a(1:2:end) = 0:3:10;
a(2:2:end) = 1:3:10;
Here is a simple and compact way:
A = 0:20;
A(3:3:end) = []

addition of one column with certain condition in another colum, like sumifs of excel

I have a matrix like this
A=[ 1 2; 2 3; 3 4; 4 5; 5 6; 6 8; 7 9; 8 5; 9 4]
Now I want to add a second column the condition is that if limit=0, and interval=3 and limit=limit+interval, or in other words, I have to sum column 2 when values of column 1, ranges like 0 to 3, 3 to 6, 6 to 9, and 9 to 12, and i want sum of corresponding values of column 2.
my solution will be like that
range- sum
0 to 3 9
3 to 6 19
6 to 9 18
like that I have a matrix of around 7000x2. In place of range just serial no may also be given.
This is just an example.
This is a job for ACCUMARRAY. First, you construct an array of indices of the values that should be added together, then you call accumarray:
%# create test data
A=[ 1 2; 2 3; 3 4; 4 5; 5 6; 6 8; 7 9; 8 5; 9 4];
%# create indices from first column
%# if you have indices already, you can use them directly
%# or you can convert them to consecutive indices via grp2idx
groupIdx = ceil(A(:,1)/3); %# 0+ to 3 is group 1, 3+ to 6 is group 2, etc
%# sum
result = accumarray(groupIdx,A(:,2),[],#sum)
result =
9
19
18
EDIT
If you need instead to count entries within the ranges, it is still a job for accumarray, only that you don't accumulate into a sum, but into a histogram.
%# use test data, groupIdx from above
A=[ 1 2; 2 3; 3 4; 4 5; 5 6; 6 8; 7 9; 8 5; 9 4];
groupIdx = ceil(A(:,1)/3); %# 0+ to 3 is group 1, 3+ to 6 is group 2, etc
%# find values to count
values2count = unique(A(:,2));
%# count the values
countsPerRange = accumarray(groupIdx,A(:,2),[],#(x){hist(x,values2count)})
%# inspect the counts for range #1
[values2count,countsPerRange{1}']
ans =
2 1
3 1
4 1
5 0
6 0
8 0
9 0

GROUP BY in MATLAB

I want to do what SQL's GROUP BY does in MATLAB. For example,
M = [
1, 5;
2, 5;
3, 5;
1, 6;
2, 6;
1,7 ]
SQL: SELECT MAX(c1), c2 FROM M(c1, c2) GROUP BY 2
Result = [
3, 5;
2, 6;
1, 7]
How can I do this in Matlab?
grpstats in the Statistics Toolbox can do this:
>> [grpstats(M(:,1), M(:,2), {'max'}) unique(M(:,2))]
ans =
3 5
2 6
1 7
If you don't mind doing some preprocessing to get the order (or if the first column is nicely built from 1 to n), you can do it like this:
accumarray([1 2 3 1]',[11 12 13 14]',[],#max)
This will give:
14
12
13
Or in your case:
accumarray(M(:,1),M(:,2),[],#max)
Note the order. The second number for example, will correspond to M(:,1) == 2
I think there is a simple solution to this.
Here is what I tested on Matlab and it worked:
>> M = [
1, 5;
2, 5;
3, 5;
1, 6;
2, 6;
1,7 ];
>> grpstats(M,M(:,2),{'max'})
ans =
3 5
2 6
1 7