Jason Thapa
Jason Thapa

Reputation: 123

most frequent element in a cell array without using unique function?

Hello I have cell array of repeating strings and numbers(class double) corresponding to the strings.

Name     Score
 'John'    90
 'Mat'     99
 'John'    98
 'Tonny'   88
 'Carl'    99
 'Rem'     88
 'Tonny'   99

How do I count the number of times the same name appears and the total score they got. For instance the total score for 'John' would be 188. I know you can use unique function to do it, but is there other way to do it beside using unique. It would be great if you guys could help me out.

Thank you.

Upvotes: 0

Views: 148

Answers (4)

cagliari2005
cagliari2005

Reputation: 271

Had a similar problem recently and found accumarray. I did not test it with a cell vector directly but it definitely works for numerical values and does exactly what you want.

names = [1,2,1,3,4,5,3]
scores = [90, 99, 98, 88, 99, 88, 99]
counts = accumarray(names,scores)

Upvotes: 0

Daniel
Daniel

Reputation: 36710

Here is a solution using accumarray

names = {'John', 'Mat', 'John', 'Tonny', 'Carl', 'Rem', 'Tonny'}
scores = [90, 99, 98, 88, 99, 88, 99]
[uniquenames,b,c]=unique(names,'stable')
counts = accumarray(c,scores)

Upvotes: 0

Luis Mendo
Luis Mendo

Reputation: 112669

I would go with unique and accumarray. But if you want to avoid unique, you can do it this way:

% // Data:
data = { 'John'    90
         'Mat'     99
         'John'    98
         'Tonny'   88
         'Carl'    99
         'Rem'     88
         'Tonny'   99}

%// Generate unique numeric labels without `unique`
N = size(data,1);
[ii, jj] = ndgrid(1:N);
[~, ind] = max(triu(reshape(strcmp(data(ii,1), data(jj,1)), N, N)));
ind = ind([true diff(ind)>0]);

%// Apply `accumarray` to that:
s = accumarray(ind(:), [data{:,2}].', [], @sum, NaN);
ind = ind([true diff(ind)>0]);
result = [data(ind,1) num2cell(s(~isnan(s)))];

In this example,

result = 
    'John'     [188]
    'Mat'      [ 99]
    'Tonny'    [187]
    'Carl'     [ 99]
    'Rem'      [ 88]

Upvotes: 2

TallBrianL
TallBrianL

Reputation: 1252

Your answer will depend on how the data is stored.

IF the names are stored in a cell array and the scores are stored as a vector you can do the following:

names = {'John', 'Mat', 'John', 'Tonny', 'Carl', 'Rem', 'Tonny'}
scores = [90, 99, 98, 88, 99, 88, 99]
ref_mat = cellfun(@(x) strcmp(names,x),names,'UniformOutput',false)
tot_score = cellfun(@(x) sum(scores(x)), ref)

Here you will create a index mat of matching names, then reference those scores and sum them. The total scores will be with respect to each name, so repeated names will have repeated totals. In this way you do not have to find unique values.

Upvotes: 1

Related Questions