excel has an equation or function to combine number in different column, as you can see in the picture below. having the same data in matlab , how can i combine numbers in a different columns.
having a d data:
a b c d
1 1 1 3
2 1 0 5
1 2 5 30
3 4 1 26
-1 1 1 3
since 111 and -111 have the same values of d, so i combine it so that 1st cell in 1st column became 111,-111 and their d become 6 because i add it up, so can matlab do that? thanks
a=[1 1 1 3;2 1 0 5; 1 2 5 30; 3 4 1 26; -1 1 1 3]
len=size(a);
x2=[]
for i=1:len(1)
s=num2str(a(i,1:len(2)-1));
s=s(s~=' ');
x2(i,:)=[str2num(s) (a(i,len(2)))];
end
Result:
x2 =
111 3
210 5
125 30
341 26
-111 3
now to find the repeated indices:
u=unique(x2(:,2));
n=histc(x2(:,2),u);
ind=find(x2(:,2)==u(n>1))
Result:
ind =
1
5
Ok now to sum and combine:
xx=x2(ind,:)
ss=sum(xx(:,2));
s=num2str(xx(:,1)');
s=strrep(s, ' ', ',')
x2(min(ind),2) = ss;
x2(ind(ind~=min(ind)),:) = []
C = num2cell(x2);
C(min(ind),1) = cellstr(s)
The final result is:
C =
'111,-111' [ 6]
[ 210] [ 5]
[ 125] [30]
[ 341] [26]
Related
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
I have a matrix A made of 1 2 and 3, e.g.,
A= [ 1 2 2 1;
3 3 1 2;
...
...
1 1 2 2]
now I want to replace 1 2 3 with different values in B according to its row. e.g.,
B= [ 4 5 6;
10 20 30;
...
...
77 88 99]
I want to replace the value in A to B in each row. e.g.,
A= [ 1 2 2 1; replace '1 2 3' with '4 5 6' respectively
3 3 1 2; replace '1 2 3' with '10 20 30' respectively
...
...
1 1 2 2] replace '1 2 3' with '77 88 99' respectively
C will be the matrix with the new assignments that I want.
C= [ 4 5 5 4;
30 30 10 20;
...
...
77 77 88 88]
I can't avoid a loop in this case, here is the quickest way that I can do:
for row_i=1:size(A,1)
C(row_i,:)=B(row_i,A(row_i,:))
end
I hate loops in MATLAB, and the actual size of A and B are large, therefore wonder if anyone can reproduce it without loop will be highly appreciated!
A = [ 1 2 2 1;
3 3 1 2;
1 1 2 2];
B = [ 4 5 6;
10 20 30;
77 88 99];
C = B(sub2ind(size(col), repmat(1:size(A, 1), size(A, 2), 1).', A));
4 5 5 4
30 30 10 20
77 77 88 88
Explanation
You're using A to indicate which column of B to use. And as you said, you want the row to be the same as the row in A. So we just need a row and column index into B for each member of A.
To get the rows, we just need to create a matrix the size of A where every element in each row is equal to the row index. Also we take care to avoid any magic numbers and actually determine the proper size.
rowindex = repmat(1:size(A, 1), size(A, 2), 1).'
1 1 1 1
2 2 2 2
3 3 3 3
Great, now that we have that, we already know the columns. That is simply A!
colindex = A
1 2 2 1
3 3 1 2
1 1 2 2
Now we just need to convert these subscripts to absolute indices using sub2ind and the size of B as a reference.
indices = sub2ind(size(B), rowindex, colindex)
1 4 4 1
8 8 2 5
3 3 6 6
Now we just need to use these to index into B and assign to C.
C = B(indices)
4 5 5 4
30 30 10 20
77 77 88 88
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),:)
I have a matrix A 4x10000, I want to use it to find another matrix C.
I'll simplify my problem with a simple example:
from a matrix A
20 4 4 74 20 20
36 1 1 11 36 36
77 1 1 15 77 77
3 4 2 6 7 8
I want, first, to find an intermediate entity B:
2 3 4 6 7 8
[20 36 77] 0 1 0 0 1 1 3
[4 1 1] 1 0 1 0 0 0 2
[74 11 15] 0 0 0 1 0 0 1
we put 1 if the corresponding value of the first line and the vector on the left, made a column in the matrix A.
the last column of the entity B is the sum of 1 of each line.
at the end I want a matrix C, consisting of vectors which are left in the entity B, but only if the sum of 1 is greater than or equal to 2.
for my example:
20 4
C = 36 1
77 1
N.B: for my problem, I use a matrix A 4x10000
See if this works for you -
%// We need to replace this as its not available in your old version of MATLAB:
%// [unqcols,~,col_match] = unique(A(1:end-1,:).','rows','stable') %//'
A1 = A(1:end-1,:).'; %//'
[unqmat_notinorder,row_ind,labels] = unique(A1,'rows');
[tmp_sortedval,ordered_ind] = sort(row_ind);
unqcols = unqmat_notinorder(ordered_ind,:);
[tmp_matches,col_match] = ismember(labels,ordered_ind);
%// OR use - "[tmp2,col_match] = ismember(A1,out,'rows');"
C = unqcols(sum(bsxfun(#eq,col_match,1:max(col_match)),1)>=2,:).'; %//'
%// OR use - "C = out(accumarray(col_match,ones(1,numel(col_match)))>=2,:).'"
This should work:
[a,~,c] = unique(A(1:end-1,:).', 'rows', 'stable');
C=a(histc(c,unique(c))>=2, :).';
Edit: For older versions of MATLAB:
D=A(1:end-1,:);
C=unique(D(:,squeeze(sum(all(bsxfun(#eq, D, permute(D, [1 3 2])))))>=2).', 'rows').':
a contains indices and their occurrences. Now the indexing needs to be changed with Hamming weight so that indices with equal hamming weight will be summed up. How to do the Hamming weight indexing? Any ready command for this in Matlab?
>> a=[1,2;2,3;5,2;10,1;12,2]
1 2
2 3
5 2
10 1
12 2
13 8
>> dec2bin(a(:,1))
ans =
0001
0010
0101
1010
1100
1101
Goal: index things by Hamming weight
HW Count
1 5 (=2+3)
2 5 (=2+1+2)
3 8 (=8)
You can do it as follows:
a = [1,2;2,3;5,2;10,1;12,2;13,8]
the following line needs to be added, to consider also a hammingweight of zero:
if nnz(a(:,1)) == numel(a(:,1)); a = [0,0;a]; end
% or just
a = [0,0;a]; %// wouldn't change the result
to get the indices
rowidx = sum( de2bi(a(:,1)), 2 )
to get the sums
sums = accumarray( rowidx+1, a(:,2) ) %// +1 to consider Hammingweight of zero
to get the Hammingweight vector
HW = unique(rowidx)
returns:
rowidx =
1
1
2
2
2
3
sums =
5
5
8
and all together:
result = [HW, sums]
%or
result = [unique(rowidx), accumarray(rowidx+1,a(:,2))]
result =
0 0
1 5
2 5
3 8
If you are bothered by the 0 0 line, filter it out
result(sum(result,2)>0,:)
The result for a = [0,2;2,3;5,2;10,1;12,2;13,8] would be:
result =
0 2
1 3
2 5
3 8
Try this -
a = [1 2
2 3
5 2
10 1
12 2
13 8]
HW = dec2bin(a(:,1)) - '0';
out = accumarray(sum(HW,2), a(:,2), [], #sum);%%// You don't need that "sum" option it seems, as that's the default operation with accumarray
final_out = [unique(sum(HW,2)) out]
Output -
a =
1 2
2 3
5 2
10 1
12 2
13 8
final_out =
1 5
2 5
3 8