Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the most MATLAB-ish way to "histogramize" a sorted cell array?

Suppose I run a 7/11, and the following 100x3 cell array sorted by the first column, time, is my sale records.

12:32:01 customer1 12
12:32:02 customer2 13
12:32:04 customer6 4
12:32:06 customer8 6
12:32:07 customer1 9
12:32:07 customer1 6
12:32:12 customer2 1
...

As you have noticed, each customer can make purchases multiple times. e.g. customer 1 actually made three different payments.

I now wish to compute the average payment of each customer. e.g. let's assume customer 1 have only made 3 payments as shown above. Then, his average payment would be (12+9+6)/3=9.

I can surely write a for loop to loop through all the entries and keep tracks of each customer. However, I feel that is not how it is supposed to be done with MATLAB.

So what is the most MATLAB-ish way of completing the task?

like image 331
Sibbs Gambling Avatar asked Dec 27 '25 20:12

Sibbs Gambling


1 Answers

Start with unique to get an integer "key" for each customer, then feed that into accumarray with the @mean function handle:

data = {'12:32:01','customer1',12; '12:32:02','customer2',13;...
        '12:32:04','customer6',4; '12:32:06','customer8',6;...
        '12:32:07','customer1',9; '12:32:07','customer1',6;...
        '12:32:12','customer2',1};
[customers,~,ic] = unique(data(:,2));
avePayment = accumarray(ic,[data{:,3}],[],@mean);

Then assemble the outputs:

>> custAvgTab = [customers num2cell(avePayment)]

custAvgTab = 

    'customer1'    [9]
    'customer2'    [7]
    'customer6'    [4]
    'customer8'    [6]

IMHO, this is quite MATLAB-ish and actually surprisingly intuitive.

NOTE: I replaced cell2mat(data(:,3)) with [data{:,3}] since I think it is better to use built-in MATLAB operations when possible.

NOTE 2: For large data, sprintfc('%d',avePayment) may be faster than num2cell(avePayment).

like image 114
chappjc Avatar answered Dec 30 '25 22:12

chappjc