2

I am trying to sort a cell matrix based on two columns using MATLAB:

ticker date price
msft 1/9/11 19.8
msft 1/8/11 18.7
csco 1/8/11 9.8
csco 1/9/11 10.0

I want to sort the matrix first by date then by ticker, so the result I want is:

ticker date price
csco 1/8/11 9.8
msft 1/8/11 18.7
csco 1/9/11 10.0
msft 1/9/11 19.8

Anyone knows how I can do that? THanks.

Stewie Griffin
  • 14,889
  • 11
  • 39
  • 70
David
  • 191
  • 1
  • 2
  • 4
  • 2
    Welcome to StackOverflow! Please read the [FAQ](http://stackoverflow.com/faq) to understand how it works. Also, if you can decide on the best answer, accept it by clicking on the check mark next to it. – Jacob Jul 13 '11 at 17:01

4 Answers4

5

I would convert the date column into the corresponding serial date number with datenum and use sortrows with the required ordering to sort the data.

Here's some code ; assume d is your 4x3 cell array from the example you gave:

d = 

'msft'    '1/9/11'    [19.8000]
'msft'    '1/8/11'    [18.7000]
'csco'    '1/8/11'    [ 9.8000]
'csco'    '1/9/11'    [     10]
  • Convert the date column to numbers with arrayfun

    d(:,2) = arrayfun(@(x){datenum(x)},d(:,2));
    
  • Sort the matrix with sortrows (date first then ticker symbol)

    d = sortrows(d,[2 1]);
    
  • Replace the date with a string with datestr.

    d(:,2) = arrayfun(@(x){datestr(x{1},'mm/dd/yy')},d(:,2));
    
Jacob
  • 34,255
  • 14
  • 110
  • 165
1

concatenate the two cell arrays into a single cell array of strings. Sort the resultant cell array of strings and get the order of the indicies. Use those indicies to sort the original cell arrays

a = {'1', '2', '2', '3'}
b = {'a', 'b', 'a', 'a'}
for i = 1:length(a)
   ab{i} = [a{i},b{i}]
end
[s,si] = sort(ab);
sorted_a = a(si);
sorted_b = b(si);

following Jacob's suggestion, if the date format you are using is not sortable alphabetically you can replace

   ab{i} = [a{i},b{i}]

with

   ab{i} = [num2str(datenum(a{i})),b{i}]
BlessedKey
  • 1,615
  • 1
  • 10
  • 16
0
[tblB,index] = sortrows(tblA,{'Height','Weight'},{'ascend','descend'})

for your specific case:

ticker date price
msft 1/9/11 19.8
msft 1/8/11 18.7
csco 1/8/11 9.8
csco 1/9/11 10.0

 

[tblB,index] = sortrows(tblA,{'date','price'},{'ascend','descend'})
CraftedCart
  • 651
  • 7
  • 16
0

Using a similar idea to @Jacob's, here is a slightly easier solution:

%# your cell array
d = {
    'msft' '1/9/11' 19.8
    'msft' '1/8/11' 18.7
    'csco' '1/8/11'  9.8
    'csco' '1/9/11' 10.0
};

%# extract 2 columns, convert to serial date, sort, apply order to original data
[~,idx] = sortrows([datenum(d(:,2),'mm/dd/yy') cell2mat(d(:,3))], [1 2]);
d = d(idx,:)

The before:

d = 
    'msft'    '1/9/11'    [19.8]
    'msft'    '1/8/11'    [18.7]
    'csco'    '1/8/11'    [ 9.8]
    'csco'    '1/9/11'    [  10]

The after:

d = 
    'csco'    '1/8/11'    [ 9.8]
    'msft'    '1/8/11'    [18.7]
    'csco'    '1/9/11'    [  10]
    'msft'    '1/9/11'    [19.8]
Community
  • 1
  • 1
Amro
  • 123,847
  • 25
  • 243
  • 454