List combinations and count how many it appears

I have 2 matrices, W and Y. Using both as references, I want to list the different combinations and count how many times it appears from Y. Only count Y if the correponsing W value is >0.
W =[ 25
0
0
28
0
0
25
0
0
25
0
0
15
14
0
0
25
0
0];
Y =[ 1 2 0 0
1 3 2 0
1 4 3 2
1 3 0 0
1 2 3 0
1 4 3 0
1 4 0 0
1 3 4 0
1 2 3 4
2 3 0 0
2 1 3 0
2 1 4 3
2 1 4 0
2 3 4 0
2 1 3 4
2 3 1 4
3 4 0 0
3 1 4 0
3 2 1 4];
Zlist =
[12;
13;
14;
23;
24;
34;]
Add 2 1 to 1 2; 3 1 to 1 3; 4 1 to 1 4; 3 2 to 2 3; 4 3 to 3 4 and 4 2 to 24
Also, for Y with more > 2 numbers in the row like [2 1 4], it will have a combinations of 2 1, 1 4, 2 4 while [2 3 4] has 2 3, 3 4 and 2 4.
Zlistcount =
[2;
1;
2;
2;
2;
2;]

4 Comments

"Add 2 1 to 1 2; 3 1 to 1 3; 4 1 to 1 4; 3 2 to 2 3; 4 3 to 3 4 and 4 2 to 24
Also, for Y with more > 2 numbers in the row like [2 1 4], it will have a combinations of 2 1, 1 4, 2 4 while [2 3 4] has 2 3, 3 4 and 2 4"
Could you explain with illustration relating to the example you gave above?
Hi Madhan, it just means that if you see a 2 1 in a row, it is the same as 1 2 so if you are counting how many times 1 2 has appareared, 2 1 should be added to it.
For examples, for 3 numbers more than 0 in a row, like 2 1 4, the combinations will be 2 1, 1 4 and 2 4. so If have a list. it will be
12 = 1
13 = 0
14 = 1
23 = 0
24 = 1
34 = 0
Then if I go to the next row with 2 3 4 , the combinations will be 2 3, 3 4, 2 4, and my new counter will be
12 = 1
13 = 0
14 = 1
23 = 0 + 1
24 = 1 + 1
34 = 0 + 1
Also, if we've counted how many 1 2 are there in Y, would we be able to tell which rows and columns they are located? For example, for 1 2, we know in W, they are situated at W(1,1) and W(13,1)
Re-edit the posting so can copy and paste into command window and execute w/o editing the columns...as is is not readable

Sign in to comment.

 Accepted Answer

YY = Y(W~=0,:);
n = sum(YY>0,2);
k = factorial(n)./factorial(n-2)/2;
ie = cumsum(k);
ib = ie - k + 1;
zc = zeros(ie(end),2);
for ii = 1:numel(ib)
zc(ib(ii):ie(ii),:) = sort(nchoosek(YY(ii,YY(ii,:)>0),2),2);
end
[i1,i2,v] = find(accumarray(zc,1));
Zlistcount = [i1,i2,v];
and without loop (as in Dpb's answer):
YY = Y(W~=0,:);
zc = sort(cell2mat(arrayfun(@(x)nchoosek(YY(x,YY(x,:)>0),2),...
(1:size(YY,1))','un',0)),2);
[i1,i2,v] = find(accumarray(zc,1));
Zlistcount = [i1,i2,v];

More Answers (1)

dpb
dpb on 9 Aug 2019
Edited: dpb on 9 Aug 2019
y=Y(W~=0,:);
z=unique(sort(cell2mat(arrayfun(@(i) nchoosek(y(i,y(i,:)~=0),2),1:size(y,1),'uni',0).'),2),'rows');
nZ=arrayfun(@(i) sum(sum(ismember(y,z(i,:)),2)==2),1:size(z,1)).';
There's no other need for W once you've cleaned out the superfluous Y.
I suspect, but haven't thought about it at all, that a clever application of accumarray might also be a solution...

4 Comments

+1 Great solution!
1 line shorter than mine which also used nchoosek() along with arrayfun().
dpb
dpb on 9 Aug 2019
Edited: dpb on 9 Aug 2019
Thanks! Wasn't going to mess w/ it but intrigued me so despite the formatting went ahead anyways...
I had just caught the typo...I hadn't pasted everything and missed the second dimension. Good spot...I eliminated the ix temporary, besides as unneeded.
"also used nchoosek() along with arrayfun()."
I wish there were a 'rows|columns' optional argument to arrayfun so didn't have to resort to the expedient of the size(x,dim) indexing argument with the array buried in the anonymous function but could pass the desired vector directly. Maybe there should be a vectorfun besides...
That's been on my mental wishlist for a long time and I'm surprised it's not already an option since it's such a common need.
Well, you can always
cellfun(@fun, num2cell(array, 2))
to iterate over the rows. Simple to type but of course, there's the overhead of the transformation to cell array.

Sign in to comment.

Categories

Tags

Asked:

JL
on 9 Aug 2019

Commented:

JL
on 10 Aug 2019

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!