How to count same values of number in column using matlab - matlab

So here's my problem i want to count the numbers of same values in a column, this my data:
a b d
2 1 5
1 3 10
1 -2 5
0 5 25
5 0 25
1 1 2
-1 -1 2
i want to count the same values of d (where d = a^2 + b^2), so this is the output i want:
a b d count
2 1 5 2
1 3 10 1
0 5 25 2
1 1 2 2
so as you can see, only positive combinations of a and b displayed. so how can i do that? thanks.

Assuming your data is a matrix, here's an accumarray-based approach. Note this doesn't address the requirement "only positive combinations of a and b displayed".
M = [2 1 5
1 3 10
1 -2 5
0 5 25
5 0 25
1 1 2
-1 -1 2]; %// data
[~, jj, kk] = unique(M(:,3),'stable');
s = accumarray(kk,1);
result = [M(jj,:) s];

Assuming your input data to be stored in a 2D array, this could be one approach -
%// Input
A =[
2 1 5
1 3 10
1 -2 5
0 5 25
5 0 25
1 1 2
-1 -1 2]
[unqcol3,unqidx,allidx] = unique(A(:,3),'stable')
counts = sum(bsxfun(#eq,A(:,3),unqcol3.'),1) %//'
out =[A(unqidx,:) counts(:)]
You can also get the counts with histc -
counts = histc(allidx,1:max(allidx))
Note on positive combinations of a and b: If you are looking to have positive combinations of A and B, you can select only those rows from A that fulfill this requirement and save back into A as a pre-processing step -
A = A(all(A(:,1:2)>=0,2),:)

Related

How to generate all possible combinations for the column vectors of a matrix, in MATLAB?

If B=[1; 2] and A=[B B B...(n times B)], how to obtain the matrix C corresponding to all the possible combinations between the column vectors of A .i.e. I want to get the combinations between n copies of the same vector.
For example, for n=3:
A =
1 1 1
2 2 2
So, C can be obtained using the function from File Exchange 'allcomb(varargin)':
C=allcomb(A(:,1),A(:,2),A(:,3))
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
In my case n is variable. How to obtain C for any value of n?
You can put the repetitions in a cell, and use the {:} syntax to put all cell elements as inputs to allcomb
n = 3;
B = [1,2];
A = repmat( {B}, n, 1 );
C = allcomb( A{:} ); % allcomb is FileExchange.
% combvec is a documented alternative.
Output:
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
Since the alphabets for each of the places is the same, this is really a base conversion. MATLAB only accepts integer bases, but we can use that integer as an index into the alphabet B:
B=[1; 2];
n = 3;
b = numel(B);
for k = 0:(b^n-1) % loop over all possible combinations
C(k+1,:) = dec2base(k, b, n);
end
C = C - '0' + 1; % convert 0..b-1 (in chars) into 1..b (in ints) for indexing
C = B(C); % index into alphabet B
Results:
>> C
C =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
The last line of the script doesn't appear to do much in this case because the alphabet happens to be the same range as our indices, but changing the alphabet to B = [7; 14] will correctly result in:
C =
7 7 7
7 7 14
7 14 7
7 14 14
14 7 7
14 7 14
14 14 7
14 14 14
Funnily enough, allcomb from MATLAB File Exchange seems to be what you want.
allcomb([1; 2],[1; 2], [1; 2])
ans =
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
To do it for any n, simply construct the matrix with:
>> n = 3;
>> repmat(B, 1, n)
ans =
1 1 1
2 2 2

Generate all possible column vectors in matlab

I am essentially trying to figure out how to generate code for basis vectors of different configurations of M objects into N different states (for example, if I had 2 snacks between 2 kids, I could have (2,0) (0,2) or (1,1), terrible example, but thats the idea)
I am struggling to figure out how to do this without going into many different loops (I want this to be automatic). The idea would be to create a Matrix where each row is a vector of length M. I would start with vec(1) = N then an if loop where if sum(vec) == N, Matrix(1,:)=vec; Then I could take vec(1)=N-i and do the same.
My only issue is I do not see how to use the if and forget it so that if I had maybe 2 objects in 5 locations, how would I do this to get (1 0 0 0 1).
I am not seeing how to do this.
You could use a recursive function:
function out = combos(M,N)
if N == 1
out = M;
else
out = [];
for i = 0:M
subout = combos(M-i,N-1);
subout(:,end+1) = i;
out = [out;subout];
end
end
I think this does what you want.
The key idea is to generate not the number of elements in each group, but the split points between groups. This can be done via combinations with repetition. Matlab's nchoosek generates combinations without repetition, but these are easily converted into what we need.
M = 5; % number of objects
N = 3; % number of groups
t = nchoosek(1:M+N-1, N-1); % combinations without repetition...
t = bsxfun(#minus, t, 1:N-1); % ...convert into combinations with repetition
t = diff([zeros(size(t,1), 1) t repmat(M, size(t,1), 1) ], [], 2); % the size of each
% group is the distance between split points
In this example, the result is
t =
0 0 5
0 1 4
0 2 3
0 3 2
0 4 1
0 5 0
1 0 4
1 1 3
1 2 2
1 3 1
1 4 0
2 0 3
2 1 2
2 2 1
2 3 0
3 0 2
3 1 1
3 2 0
4 0 1
4 1 0
5 0 0
This is a similar approach to Luis' without bsxfun. Because we don't like fun.
n = 5;
k = 3;
c = nchoosek(n+k-1, k-1);
result = diff([zeros(c, 1) nchoosek(1:(n+k-1), k-1) ones(c, 1)*(n+k)], [], 2) - 1;
This creates the partitions of the integer n with length k. Given an array of length n + (k-1), we find all combinations of (k-1) places to place partitions between the (unary) integers. For 5 items and 3 locations, we have 7 choices of where to put the partitions:
[ 0 0 0 0 0 0 0 ]
If our chosen combination is [2 4], we replace positions 2 and 4 with partitions to look like this:
[ 0 | 0 | 0 0 0 ]
The O's give the value in unary, so this combination is 1 1 3. To recover the values easily, we just augment the combinations with imaginary partitions at the next values to the left and right of the array (0 and n+k) and take the difference and subtract 1 (because the partitions themselves don't contribute to the value):
diff([0 2 4 8]) - 1
ans =
1 1 3
By sliding the partitions in to each possible combination of positions, we get all of the partitions of n.
Output:
result =
0 0 5
0 1 4
0 2 3
0 3 2
0 4 1
0 5 0
1 0 4
1 1 3
1 2 2
1 3 1
1 4 0
2 0 3
2 1 2
2 2 1
2 3 0
3 0 2
3 1 1
3 2 0
4 0 1
4 1 0
5 0 0

MATLAB generate all ways that n items can be put into m bins?

I want to find all ways that n items can be split among m bins. For example, for n=3 and m=3 the output would be (the order doesn't matter):
[3 0 0
0 3 0
0 0 3
2 1 0
1 2 0
0 1 2
0 2 1
1 0 2
2 0 1
1 1 1]
The algorithm should be as efficient as possible, preferrably vectorized/using inbuilt functions rather than for loops. Thank you!
This should be pretty efficient.
It works by generating all posible splitings of the real interval [0, n] at m−1 integer-valued, possibly coincident split points. The lengths of the resulting subintervals give the solution.
For example, for n=4 and m=3, some of the possible ways to split the interval [0, 4] at m−1 points are:
Split at 0, 0: this gives subintervals of lenghts 0, 0, 4.
Split at 0, 1: this gives subintervals of lenghts 0, 1, 3.
...
Split at 4, 4: this gives subintervals of lenghts 4, 0, 0.
Code:
n = 4; % number of items
m = 3; % number of bins
x = bsxfun(#minus, nchoosek(0:n+m-2,m-1), 0:m-2); % split points
x = [zeros(size(x,1),1) x n*ones(size(x,1),1)]; % add start and end of interval [0, n]
result = diff(x.').'; % compute subinterval lengths
The result is in lexicographical order.
As an example, for n = 4 items in m = 3 bins the output is
result =
0 0 4
0 1 3
0 2 2
0 3 1
0 4 0
1 0 3
1 1 2
1 2 1
1 3 0
2 0 2
2 1 1
2 2 0
3 0 1
3 1 0
4 0 0
I'd like to suggest a solution based on an external function and accumarray (it should work starting R2015a because of repelem):
n = uint8(4); % number of items
m = uint8(3); % number of bins
whichBin = VChooseKR(1:m,n).'; % see FEX link below. Transpose saves us a `reshape()` later.
result = accumarray([repelem(1:size(whichBin,2),n).' whichBin(:)],1);
Where VChooseKR(V,K) creates a matrix whose rows are all combinations created by choosing K elements of the vector V with repetitions.
Explanation:
The output of VChooseKR(1:m,n) for m=3 and n=4 is:
1 1 1 1
1 1 1 2
1 1 1 3
1 1 2 2
1 1 2 3
1 1 3 3
1 2 2 2
1 2 2 3
1 2 3 3
1 3 3 3
2 2 2 2
2 2 2 3
2 2 3 3
2 3 3 3
3 3 3 3
All we need to do now is "histcount" the numbers on each row using positive integer bins to get the desired result. The first output row would be [4 0 0] because all 4 elements go in the 1st bin. The second row would be [3 1 0] because 3 elements go in the 1st bin and 1 in the 2nd, etc.

How to know the if some combination repeats using matlab

Please allow me to post this admin:
ok so this is my problem, i want to generate all combination of a, and b, for example 1 and 2, having a combinations of (1,2), (2,1),(-1,2), and (2,-1), so 4 combination, but i want only one combination as representative of all 4 combination to be display in output for example only (1,2). so this is my draft code:
fprintf(' a b z \n _ _ _ \n');
for a= -1:3
for b=-1:3
z=a^2 + b^2
end
end
ctr=1;
i(:,3) %the position of z in array
for x =1:length(z) %the length of z array
if z = i(1,1)
ctr = ctr +1;
else
fprintf(' %d %d %d\n',a,b,z);
end
end
so this the output i want:
a b z no. of repetitions
1 1 2 4
1 0 1 4
1 2 5 4
1 3 10 4
0 2 4 2
0 3 9 2
2 2 8 1
2 3 13 2
3 3 18 1
0 0 0 1
no. of repetition means how many possible combination of a and b can generate
in=-1:3
%calculate z
[a,b]=meshgrid(in);
z=a.^2+b.^2;
%sort absolute values ascending, which allows to use unique
ac=sort(abs([a(:) b(:)]),2);
%use unique to identify duplicates
[f,g,h]=unique(ac,'rows');
%count
cnt=histc(h,1:max(h));
disp([a(g),b(g),z(g),cnt])
The output is:
0 0 0 1
1 0 1 4
2 0 4 2
3 0 9 2
1 1 2 4
2 1 5 4
3 1 10 4
2 2 8 1
3 2 13 2
3 3 18 1

Permute the Matrix with Given Index

Given A is symmetry matrix with size n and
A =
1 2 3 4 5 % The Position
1 [0 5 2 4 1
2 5 0 3 0 2
3 2 3 0 0 0
4 4 0 0 0 5
5 1 2 0 5 0]
B is a row vector that permute the matrix A row and column
B = [2 4 1 5 3]
The output that I want is
C =
2 4 1 5 3 % The New Position given by Matrix B
2 [0 0 5 2 3
4 0 0 4 5 0
1 5 4 0 1 2
5 2 5 1 0 0
3 3 0 2 0 0]
I can get the output by using simple for loop
index = [2,4,1,5,3];
C = zeros(5,5);
for i = 1:5
for j = 1:5
% Position of in square matrix n
% (i,j) = (i-1)*n + j
C(i,j) = A((index(i)-1)*5+index(j));
end
end
However, if I want to permute a matrix with size 80x80, then I need to run 1600 times in order to get the output.
Is there any simple trick to do it instead of using for loop?
You should be able to rearrange your matrices as follows:
C = A(index,index);
This rearranges each dimension according to the index variable independently.