Loren on the Art of MATLAB

November 27th, 2007

uniquely MATLAB

What makes MATLAB unique? You have your choice regarding which element unique returns when there are repeated values in an array. What I wonder about is why it matters.

Contents

Which Index to Return

If you look at the help for unique

helptext = help('unique');
helptext = helptext(1:650)
helptext =
 UNIQUE Set unique.
    B = UNIQUE(A) for the array A returns the same values as in A but
    with no repetitions. B will also be sorted. A can be a cell array of 
    strings.
 
    UNIQUE(A,'rows') for the matrix A returns the unique rows of A.
 
    [B,I,J] = UNIQUE(...) also returns index vectors I and J such
    that B = A(I) and A = B(J) (or B = A(I,:) and A = B(J,:)).
    
    [B,I,J] = UNIQUE(...,'first') returns the vector I to index the
    first occurrence of each unique value in A.  UNIQUE(...,'last'),
    the default, returns the vector I to index the last occurrence.
 
    See also UNION, INTERSECT, SETDIFF, SETXOR, ISMEMBER.

 

you will see that you can get the index value returned. By default, unique returns the last index, but you are also request the first one. Additionally, you can look for unique rows, something especially useful for character data.

unique in Action

Here's a quick demonstration of unique acting on a vector of birthdates in my extended family (just the day of the month) and the unique values.

birthdates = [11 12 22 1 14 4 25 28 1 7 19 12]
bds = unique(birthdates)
birthdates =
    11    12    22     1    14     4    25    28     1     7    19    12
bds =
     1     4     7    11    12    14    19    22    25    28

Now, here are the indices back into the original birthdates.

[bds, bdlast] = unique(birthdates);
bdlast
bdlast =
     9     6    10     1    12     5    11     3     7     8

And the first occurrences.

[bds, bdfirst] = unique(birthdates,'first');
bdfirst
bdfirst =
     4     6    10     1     2     5    11     3     7     8

What I Don't Know

What I can't think of is why I care about the index. I am sure there are applications where it matters because there is related data that needs to come along. But what does the occurrence order have to do with anything?

Your Examples

Would you please share your code examples in which it mattered to you which instance of a non-unique element you captured? Let me know here.


Get the MATLAB code

Published with MATLAB® 7.5

22 Responses to “uniquely MATLAB”

  1. JWagberg replied on :

    I used the index feature of UNIQUE just an hour ago. I had one cellstr with names and a corresponding data array with same number of columns. I wanted to keep only the first of any duplicatly named column. The solution:

    [dummy,ix]=unique(Names, ‘first’);
    Data=Data(:,sort(ix));

  2. Loren replied on :

    Thanks for the reply! But why did you care if it was the first?

    –Loren

  3. JWagberg replied on :

    The data comes originally from a log file where names are positions in a process where some measurements are made more frequently than others. I have the a priori knowledge that the first measurement at a position represents the startup condition, so an easy way to collect the all the startup conditions was to use UNIQUE.

  4. Daniel replied on :

    Well, lets say you have one matrix with test identifiers, one with test times and one with test results. In that case one might sort all the matrices on test time (I believe you did an article on that some time back), then check uniqueness of the test identifiers, and thus present the result of the last of each test performed. Naturally one could sort backwards, but either way the direction from which the search is done matters very much.

    Sincerely
    Daniel Armyr

  5. ramiro replied on :

    hi Loren
    I use the ‘unique’ command within a particle tracking GUI. This GUI lets the user define parameters to identify ‘objects’ in 2D microscopy images - belonging to a time series or time-lapse - and eliminate those that don’t follow special criteria (e.g. size).
    The code creates a 3D labeled matrix (e.g. (x,y,time)). The GUI has a listbox with the numerical identity of all the objects. If the user wants to find the first time-point where that object exists within the time-series he/she just needs to click any element of the list box. The ‘unique(labeled,’first’)’ function is great because I can immediately find the first occurrence of any selected object.
    sorry for my long email,
    best
    ramiro

  6. ramiro replied on :

    hi loren
    I want to create a Help GUI similar in format to the one present in Word/Excel, or other Microsoft applications. Do you happen to know whether Matlab has special tools for this or alternatively, do you know any other language that has an editor to help build a Microsoft-like Help?
    best
    ramiro

  7. Loren replied on :

    Ramiro-

    Thanks for adding your comments on unique.

    GUIS are not my expertise. You may want to check with the desktop folks: http://blogs.mathworks.com/desktop/

    –Loren

  8. Ken Orr replied on :

    Hi Ramiro,

    I don’t know of any tools that will let you create a help UI similar to that of Word or Excel in MATLAB.

    You can, however, hook into the MATLAB help system. Check out this documentation for more info:

    http://www.mathworks.com/access/helpdesk/help/techdoc/matlab_env/f3-40358.html

    -Ken

  9. ramiro replied on :

    hi Ken
    thanks for the tip. I don’t know whether the HTML Help files created within Matlab will run in a stand-alone application. Do you?
    best

  10. ramiro replied on :

    hi Loren
    Do you know whether it’s possible to hide the installation of the MCRinstaller in stand-alone applications? I want the end-users of my stand-alone application to follow a traditional installation (only 1 installation file e.g. setup.exe). For this purpose I thought about using a commertial installer builder that takes a package of files and creates a setup.exe that guides to user for the installation. I would like the MCRinstaller to be installed through this setup.exe and not independently.
    best regards
    ramiro

  11. Loren replied on :

    Ramiro-

    Please contact technical support with your question here as it is not on topic and I am not an expert in that area. Thank you.

    –Loren

  12. Duane Hanselman replied on :

    Loren: Would you not reply to folks who ask you unrelated technical questions here? It seems this venue is provided to comment on your Art of MATLAB blog, not to get personal technical advice. Even your replies that politely point people elsewhere encourage yet more requests for assistance. So the only way to stop it is to not respond. Thanks. I like reading pertinent comments people make, but I don’t like to have to trod through a bunch of them just to find the pertinent ones.

    BTW: I’ve got a homework problem to do in MATLAB. I don’t know how to get started on it. If I post it here, would you work on it in your spare time and send me the results in a form that I can hand in. It is due at 3pm today. That should give someone with your vast experience plenty of time to get it done. I will offer to put it on the FEX so others can download it in the future. I will gladly acknowledge your help in doing it. :-)

  13. Christoph Ortner replied on :

    In 2D finite element meshes, one can extract the edges from the elements using the unique command. From the second index set which is returned (to recover the original) one can then extract some additional information such as adjacency relations, whether edges are boundary edges or interior edges, etc.

    But really, those are just vectorization tricks which I wouldn’t use in any other language.

    Christoph

  14. Sean Little replied on :

    I care a lot about the order of uniqueness. There are many times when I was using previous versions of Matlab (mostly 2006a) where I would have loved to have a feature like this. Instead I would use the arrayfun command with find(…’first’ or ‘last’).

    Explaining why I care is kind of hard, and I can’t remember a good example off the top of my head. But to give a round-about explanation, one of the main reasons I use the indx output of the unique function was to apply that index to another array. It is in the other array that I care about order, where it can make a big difference which of the unique values came first.

  15. Sebastian Schmeier replied on :

    Hi Loren,

    I am relatively new to Matlab or lets say I haven’t used it in quite a while. I am sure that the problem that I solved here with unique can be solved most likely in a much more elegant way, but anyway.

    What I have is a matrix e.g.

    m =
    1 1 54
    2 1 46
    1 1 45
    2 2 44
    1 3 34
    2 1 32
    1 1 23

    col 1 and 2 represents a key (that I call edge) and the 3rd col is a weight. The matrix m is ordered according to the weight.
    What I want a matrix where I have unique edges associated with the highest weight that appears in the matrix for that edge.

    My approach:

    % flip m to sort edges in ascending order (according to weight)
    m = flipud(m);

    % make unique according to edge
    [b, index, index2] = unique(m(:,1:2), ‘rows’);

    % attach original weights of the uniq edges
    m2 = [b, m(index,3)];

    Cheers,
    Seb

  16. Jose Miguel replied on :

    Dear Loren,

    Here’s an example where the order of repetitions in an array matters,
    I’m constantly dealing with wind data where we have about 52000 data every year (one every 10 minutes).

    I always make a date vector with the help of datenum(year,month,day,hour,minute,second) so I can work with a numeric array.

    When I’m cleaning wind data I need to check if there are data repetitions and where (so I need to find repetitions in the date vector and know where it happens in order to remove the bad ones). I also need to find when elements in this vector don´t grow, as it should finally consist of growing elements (for example data from 2005 to 2008).

    Thank you very much for your help

  17. Loren replied on :

    Jose Miguel-

    Thanks for saying why the order matters to you.

    All of the things you mention are possible. If you are stuck, why not post what you’ve got to the newsgroup: http://www.mathworks.com/matlabcentral/newsreader/
    to get some ideas.

    –loren

  18. Jose Miguel replied on :

    Dear Loren,

    Thank you very much,
    I’ve posted what I’ve got to the newsgroup,

    Thank you very much for helping

    Josemi

  19. Daniel Goodman replied on :

    Using unique() with a combination of ‘rows’ and cell arrays would be useful, and this functionality is currently unavailable. For instance, if I have:

    { ‘thing_one’, ‘a’;
    ‘thing_one’, ‘b’;
    ‘thing_one’, ‘b’;
    ‘thing_two’, ‘a’;
    ‘thing_two’, ‘b’;
    ‘thing_two’, ‘b’;
    }

    and I want back the unique rows:

    { ‘thing_one’, ‘a’;
    ‘thing_one’, ‘b’;
    ‘thing_two’, ‘a’;
    ‘thing_two’, ‘b’;
    }

    I cannot use unique() out of the box.

    One could get the same result by concatenating each row into one char string (also converting any numbers to chars) and then use unique(), but this seems a little dodgy.

  20. Loren replied on :

    Daniel-

    If you could please request this enhancement via technical support, that would be great. It counts much more prominently if it comes from a user than if it comes from me ;-)

    –Loren

  21. Jerry replied on :

    Hi Loren,
    I am not sure if this is the right place to request your suggestion in regards to the NON-NUMERIC or SYMBOLIC INDEXING in MATLAB. If not, please advise how should I submit this query for you.

    I want to be able to index an array using some kind of symbolic or non-numeric indices. Let’s say,
    US_states=[’AL’, ‘AK’, ‘AZ’, …., ‘WR’, ‘WY’]
    I want to be able to say, US_states[’AK’] or US_states(’AK’) and get 2 as answer or similaraly US_states[’WY’] or US_states(’WY’) and get 50 as answer.

    Also, if I create a 50×50 matrix of these states, say - Neighbors. where any given element in the matrix represents whether the 2 states are neighbor (basically, an adjacency matrix), I want to be able to say, Neighbors(’CA’,'NY’) and get 0 as answer, since they are not neighbors.

    In nutshell, how do I implement, symbolic or non-numeric indexing in MATLAB? As you may agree, the data values are simple integers and the indices are non-numeric and if possible, I would prefer to use basic array or matrix concepts instead of cell-arrays to keep it scalable for large scale data matrices. But any or all possible approaches will be most welcome.

    Please advise. Thanks!

    Sincerely,
    Jerry

  22. Loren replied on :

    Jerry-

    You might consider using containers.Map for your indexing example. See this post for some examples. Another possibility is to use the dataset array from Statistics Toolbox. Here’s an example.

    –Loren

Leave a Reply

Wrap code fragments inside <pre> tags, like this:

<pre class="code">
a = magic(3);
sum(a)
</pre>

If you have a "<" character in your code, either follow it with a space or replace it with "&lt;" (including the semicolon).


Loren Shure works on design of the MATLAB language at The MathWorks. She writes here about once a week on MATLAB programming and related topics.

  • Jun: I totally can not believe it, Loren. You are really helpful. Thank you so much, MATLAB master!
  • Loren: Wow folks- Always lots of interest when there’s a quickie to try out! I will only make 2 general...
  • Loren: Jun- ismember is your friend here: >> [aa,ind] = ismember(Array2,Arra y1) aa = 1 1 1 1 1 1 1 ind = 1 2 1 4 4 3...
  • Dan: I like the first way better than the second way. Combining the arrays into one and running any is nice, although...
  • James Myatt: How about I = (a == 0 | b == 0); a(I) = []; b(I) = [];
  • Tunc: Hello Loren, love your blog because of such inspiring and challenging comments to such ’small’...
  • Pekka Kumpulainen: Here is my tradeoff. I usually want to keep the original variables as they are most probably...
  • Iain: Followup: Of course, to allow NaNs (counting them as non-zero): mask = (a~=0) & (b~=0); The mask says “a...
  • Matt Fig: I would usually go with something like this: y = a&b; x = a(y); y = b(y); But I was surprised to find...
  • kk: c=all([a;b]) a(c) a(b)

These postings are the author's and don't necessarily represent the opinions of The MathWorks.