{"id":3541,"date":"2020-01-31T16:30:59","date_gmt":"2020-01-31T21:30:59","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=3541"},"modified":"2020-01-31T16:47:56","modified_gmt":"2020-01-31T21:47:56","slug":"repeated-indexing-in-matlab","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2020\/01\/31\/repeated-indexing-in-matlab\/","title":{"rendered":"Repeated Indexing in MATLAB"},"content":{"rendered":"\r\n\r\n<div class=\"content\"><!--introduction--><p>Indexing is a <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/indexing\/?s_tid=Blog_loren_Category\">popular topic<\/a> I write about from time to time. Today I want to focus on what happens when there are duplicate indices.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#77239b41-a14e-42b7-a5a0-3d3ced915fa6\">Accessing Array Elements with Repeated Indices<\/a><\/li><li><a href=\"#9c2cefc8-f8f4-46d4-bbbc-c931f9f8ee29\">Replicated Elements for Assignment to Output<\/a><\/li><li><a href=\"#b36888a0-a743-4617-bd60-0819f10c4a14\">How to Achieve Accumulation Behavior<\/a><\/li><li><a href=\"#f72a4628-1cbf-4322-bb23-4410450d43af\">What Are Your Indexing Challenges When Handling Repeated Indices?<\/a><\/li><\/ul><\/div><h4>Accessing Array Elements with Repeated Indices<a name=\"77239b41-a14e-42b7-a5a0-3d3ced915fa6\"><\/a><\/h4><p>Suppose I want to make <tt>numdups<\/tt> copies of the elements in odd locations in a vector, <tt>vec<\/tt>.<\/p><pre class=\"codeinput\">vec = [-40; exp(1); pi; 17; 42];\r\nnumdups = 3;\r\noddlocs = 1:2:length(vec);\r\nlocs = oddlocs(ones(1,numdups),:);\r\nlocs = locs(:)\r\nnewvec = vec(locs(:))\r\n<\/pre><pre class=\"codeoutput\">locs =\r\n     1\r\n     1\r\n     1\r\n     3\r\n     3\r\n     3\r\n     5\r\n     5\r\n     5\r\nnewvec =\r\n  -40.0000\r\n  -40.0000\r\n  -40.0000\r\n    3.1416\r\n    3.1416\r\n    3.1416\r\n   42.0000\r\n   42.0000\r\n   42.0000\r\n<\/pre><p>As you can see, since I requested some repeated values, MATLAB returned them to me.<\/p><p>Just in case you need some clarification, let me explain what's going on here.  After creating my array and identifying the location of values I wish to repeat (<tt>oddlocs<\/tt>), I reshape this array into a column vector <tt>locs<\/tt>, and use this array, with its repeated values, to index into the rows I requested, including all the columns (but there is only 1 column here).<\/p><p>Here's an even simpler example that I will extend further.<\/p><pre class=\"codeinput\">subs = [1; 3; 3];\r\nnewvec = vec(subs)\r\n<\/pre><pre class=\"codeoutput\">newvec =\r\n  -40.0000\r\n    3.1416\r\n    3.1416\r\n<\/pre><p>I create my indices - and you can see that I want the first element followed by the 3rd one twice.  Let's start with the right-hand side. From a semantic, or meaning, point of view, MATLAB creates a new temporary array extracting the pieces of <tt>vec<\/tt> requested.  Following that, the values in the temporary array are assigned to the output <tt>newvec<\/tt>.<\/p><p>Here's how you can create a matrix from replicated columns.  First by indexing,<\/p><pre class=\"codeinput\">threecols = vec(:,[1 1 1]) <span class=\"comment\">% or vec(:, ones(1,numdups)<\/span>\r\n<\/pre><pre class=\"codeoutput\">threecols =\r\n  -40.0000  -40.0000  -40.0000\r\n    2.7183    2.7183    2.7183\r\n    3.1416    3.1416    3.1416\r\n   17.0000   17.0000   17.0000\r\n   42.0000   42.0000   42.0000\r\n<\/pre><p>by matrix multiplication<\/p><pre class=\"codeinput\">threecols = vec * [1 1 1] <span class=\"comment\">% or vec * ones(1,numdups)<\/span>\r\n<\/pre><pre class=\"codeoutput\">threecols =\r\n  -40.0000  -40.0000  -40.0000\r\n    2.7183    2.7183    2.7183\r\n    3.1416    3.1416    3.1416\r\n   17.0000   17.0000   17.0000\r\n   42.0000   42.0000   42.0000\r\n<\/pre><p>and <tt><a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/repmat.html\">repmat<\/a><\/tt>.<\/p><pre class=\"codeinput\">threecols = repmat(vec,1,3)\r\n<\/pre><pre class=\"codeoutput\">threecols =\r\n  -40.0000  -40.0000  -40.0000\r\n    2.7183    2.7183    2.7183\r\n    3.1416    3.1416    3.1416\r\n   17.0000   17.0000   17.0000\r\n   42.0000   42.0000   42.0000\r\n<\/pre><p>You may also be interested in <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/repelem.html\"><tt>repelem<\/tt><\/a>.<\/p><p>Please note that you often do not need any of these techniques for certain computations that can be efficiently accomplished with the older <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/bsxfun.html\"><tt>bsxfun<\/tt><\/a>, and, more recently, the, in my opinion elegant, implicit expansion behavior (<a href=\"https:\/\/blogs.mathworks.com\/loren\/2016\/10\/24\/matlab-arithmetic-expands-in-r2016b\/\">1<\/a>, <a href=\"https:\/\/blogs.mathworks.com\/loren\/2016\/11\/10\/more_thoughts_about_implicit_expansion\">2<\/a>) that you can use to \"expand\" singleton dimensions.<\/p><h4>Replicated Elements for Assignment to Output<a name=\"9c2cefc8-f8f4-46d4-bbbc-c931f9f8ee29\"><\/a><\/h4><p>Now let's see what we need to do if we have repeated indices in an assignment.<\/p><pre class=\"codeinput\">newvec = vec;\r\nnewvec(subs) = vec(subs) + 10\r\n<\/pre><pre class=\"codeoutput\">newvec =\r\n  -30.0000\r\n    2.7183\r\n   13.1416\r\n   17.0000\r\n   42.0000\r\n<\/pre><p>What you see here is element 1 growing by 10 and same for element 3. However, we have repeated the element 3 index.  So the computed right-hand side has element 1 and 2 copies of the updated element 3 - updated each in the same way, since that's what the code says to do. Remember I said that the MATLAB behavior is as if we placed the right-hand side into a temporary array.  Once we have finished computing the right-hand side, MATLAB works on the assignment.  Head top to bottom (even for multidimensional arrays, since MATLAB stores the data in a column-major format), and it  replaces element 1 with a new value, element 3 with a new value, and then does the latter one more time.  No extra accumulation of 10s for element 3.  But maybe you wanted to accumulate the results for repeated elements, but it's not so tidy that you can simply use something like <tt><a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/cumsum.html\">cumsum<\/a><\/tt>.<\/p><h4>How to Achieve Accumulation Behavior<a name=\"b36888a0-a743-4617-bd60-0819f10c4a14\"><\/a><\/h4><p>You may now that you can create and use <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/sparse.html\"><tt>sparse<\/tt><\/a> matrices in MATLAB.  From <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/sparse.html#bul62_1\">the doc<\/a>, you can see that you can accumulate values when constructing a sparse matrix.  This has been so handy that eventually we made an analogous function, <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/accumarray.html\"><tt>accumarray<\/tt><\/a> for non-sparse arrays as well.<\/p><p>Time for an example.  I want to compute something like   vec(subs) = vec(subs) + 10 with the difference being that I want repeated indices to accumulate the number of 10s represented by the repeated indices.<\/p><pre class=\"codeinput\">vec = (1:5)'\r\nsubs = [1; 3; 3];\r\n<\/pre><pre class=\"codeoutput\">vec =\r\n     1\r\n     2\r\n     3\r\n     4\r\n     5\r\n<\/pre><p>Here's the right-hand side as above.<\/p><pre class=\"codeinput\">vec(subs)\r\n<\/pre><pre class=\"codeoutput\">ans =\r\n     1\r\n     3\r\n     3\r\n<\/pre><pre class=\"codeinput\">[uniquevals,~,idxUnique] = unique(subs)\r\n<\/pre><pre class=\"codeoutput\">uniquevals =\r\n     1\r\n     3\r\nidxUnique =\r\n     1\r\n     2\r\n     2\r\n<\/pre><p>Notice that I call the function <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/unique.html\"><tt>unique<\/tt><\/a> and retrieve the third output, the actual locations of the unique indices as they appear in the output.<\/p><pre class=\"codeinput\">vec(uniquevals) = vec(uniquevals) + accumarray(idxUnique, 10)\r\n<\/pre><pre class=\"codeoutput\">vec =\r\n    11\r\n     2\r\n    23\r\n     4\r\n     5\r\n<\/pre><p>Finally let me return to the initial vector from the beginning of the post.  I'm guessing you fully understand what's happening here now.<\/p><pre class=\"codeinput\">subs = [1; 3; 3];\r\nvec = [-40; exp(1); pi; 17; 42];\r\nnewvec = vec;\r\n[uniquesubs,~,idxUnique] = unique(subs);\r\nnewvec(uniquesubs) =  vec(uniquesubs) + accumarray(idxUnique, 10)\r\n<\/pre><pre class=\"codeoutput\">newvec =\r\n  -30.0000\r\n    2.7183\r\n   23.1416\r\n   17.0000\r\n   42.0000\r\n<\/pre><h4>What Are Your Indexing Challenges When Handling Repeated Indices?<a name=\"f72a4628-1cbf-4322-bb23-4410450d43af\"><\/a><\/h4><p>Wondering if you have had some challenges not covered here when dealing with repeated indices.  Let me know <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=3541#respond\">here<\/a>.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_26ac34791ca7436d841545a2b6073940() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='26ac34791ca7436d841545a2b6073940 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 26ac34791ca7436d841545a2b6073940';\r\n    \r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n \r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        copyright = 'Copyright 2020 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\\n');\r\n\r\n        d.title = title + ' (MATLAB code)';\r\n        d.close();\r\n    }   \r\n     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_26ac34791ca7436d841545a2b6073940()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; R2019b<br><\/p><\/div><!--\r\n26ac34791ca7436d841545a2b6073940 ##### SOURCE BEGIN #####\r\n%% Repeated Indexing in MATLAB\r\n% Indexing is a\r\n% <https:\/\/blogs.mathworks.com\/loren\/category\/indexing\/?s_tid=Blog_loren_Category\r\n% popular topic> I write about from time to time. Today I want to focus on\r\n% what happens when there are duplicate indices.\r\n%% Accessing Array Elements with Repeated Indices\r\n% Suppose I want to make |numdups| copies of the elements in odd locations\r\n% in a vector, |vec|.\r\nvec = [-40; exp(1); pi; 17; 42];\r\nnumdups = 3;\r\noddlocs = 1:2:length(vec); \r\nlocs = oddlocs(ones(1,numdups),:);\r\nlocs = locs(:)\r\nnewvec = vec(locs(:))\r\n%%\r\n% As you can see, since I requested some repeated values, MATLAB returned\r\n% them to me.\r\n%%\r\n% Just in case you need some clarification, let me explain what's going on\r\n% here.  After creating my array and identifying the location of values I\r\n% wish to repeat (|oddlocs|), I reshape this array into a column vector\r\n% |locs|, and use this array, with its repeated values, to index into the\r\n% rows I requested, including all the columns (but there is only 1 column\r\n% here).\r\n%%   \r\n% Here's an even simpler example that I will extend further.\r\nsubs = [1; 3; 3];\r\nnewvec = vec(subs)\r\n%%\r\n% I create my indices - and you can see that I want the first element\r\n% followed by the 3rd one twice.  Let's start with the right-hand side.\r\n% From a semantic, or meaning, point of view, MATLAB creates a new\r\n% temporary array extracting the pieces of |vec| requested.  Following\r\n% that, the values in the temporary array are assigned to the output\r\n% |newvec|.\r\n%%\r\n% Here's how you can create a matrix from replicated columns.  First by\r\n% indexing,\r\nthreecols = vec(:,[1 1 1]) % or vec(:, ones(1,numdups)\r\n%%\r\n% by matrix multiplication \r\nthreecols = vec * [1 1 1] % or vec * ones(1,numdups)\r\n%%\r\n% and |<https:\/\/www.mathworks.com\/help\/matlab\/ref\/repmat.html\r\n% repmat>|.\r\nthreecols = repmat(vec,1,3)\r\n%%\r\n% You may also be interested in\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/repelem.html |repelem|>.\r\n%%\r\n% Please note that you often do not need any of these techniques for\r\n% certain computations that can be efficiently accomplished with the older\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/bsxfun.html |bsxfun|>, and,\r\n% more recently, the, in my opinion elegant, implicit expansion behavior\r\n% (<https:\/\/blogs.mathworks.com\/loren\/2016\/10\/24\/matlab-arithmetic-expands-in-r2016b\/\r\n% 1>,\r\n% <https:\/\/blogs.mathworks.com\/loren\/2016\/11\/10\/more_thoughts_about_implicit_expansion\r\n% 2>) that you can use to \"expand\" singleton dimensions.\r\n\r\n%% Replicated Elements for Assignment to Output\r\n% Now let's see what we need to do if we have repeated indices in an\r\n% assignment.\r\nnewvec = vec;\r\nnewvec(subs) = vec(subs) + 10\r\n%%\r\n% What you see here is element 1 growing by 10 and same for element 3.\r\n% However, we have repeated the element 3 index.  So the computed\r\n% right-hand side has element 1 and 2 copies of the updated element 3 -\r\n% updated each in the same way, since that's what the code says to do.\r\n% Remember I said that the MATLAB behavior is as if we placed the\r\n% right-hand side into a temporary array.  Once we have finished computing\r\n% the right-hand side, MATLAB works on the assignment.  Head top to bottom\r\n% (even for multidimensional arrays, since MATLAB stores the data in a\r\n% column-major format), and it  replaces element 1 with a new value,\r\n% element 3 with a new value, and then does the latter one more time.  No\r\n% extra accumulation of 10s for element 3.  But maybe you wanted to\r\n% accumulate the results for repeated elements, but it's not so tidy that\r\n% you can simply use something like\r\n% |<https:\/\/www.mathworks.com\/help\/matlab\/ref\/cumsum.html cumsum>|.\r\n\r\n%% How to Achieve Accumulation Behavior\r\n% You may now that you can create and use\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/sparse.html |sparse|> matrices\r\n% in MATLAB.  From\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/sparse.html#bul62_1 the doc>,\r\n% you can see that you can accumulate values when constructing a sparse\r\n% matrix.  This has been so handy that eventually we made an analogous\r\n% function, <https:\/\/www.mathworks.com\/help\/matlab\/ref\/accumarray.html\r\n% |accumarray|> for non-sparse arrays as well.\r\n%\r\n% Time for an example.  I want to compute something like\r\n%   vec(subs) = vec(subs) + 10\r\n% with the difference being that I want repeated indices to accumulate the\r\n% number of 10s represented by the repeated indices.\r\nvec = (1:5)'\r\nsubs = [1; 3; 3];\r\n%%\r\n% Here's the right-hand side as above.\r\nvec(subs)\r\n%%\r\n[uniquevals,~,idxUnique] = unique(subs)\r\n%%\r\n% Notice that I call the function\r\n% <https:\/\/www.mathworks.com\/help\/matlab\/ref\/unique.html |unique|> and\r\n% retrieve the third output, the actual locations of the unique indices\r\n% as they appear in the output.\r\nvec(uniquevals) = vec(uniquevals) + accumarray(idxUnique, 10) \r\n%%\r\n% Finally let me return to the initial vector from the beginning of the\r\n% post.  I'm guessing you fully understand what's happening here now.\r\nsubs = [1; 3; 3];\r\nvec = [-40; exp(1); pi; 17; 42];\r\nnewvec = vec;\r\n[uniquesubs,~,idxUnique] = unique(subs);\r\nnewvec(uniquesubs) =  vec(uniquesubs) + accumarray(idxUnique, 10)\r\n\r\n%% What Are Your Indexing Challenges When Handling Repeated Indices?\r\n% Wondering if you have had some challenges not covered here when dealing\r\n% with repeated indices.  Let me know\r\n% <https:\/\/blogs.mathworks.com\/loren\/?p=3541#respond  here>.\r\n\r\n##### SOURCE END ##### 26ac34791ca7436d841545a2b6073940\r\n-->","protected":false},"excerpt":{"rendered":"<!--introduction--><p>Indexing is a <a href=\"https:\/\/blogs.mathworks.com\/loren\/category\/indexing\/?s_tid=Blog_loren_Category\">popular topic<\/a> I write about from time to time. Today I want to focus on what happens when there are duplicate indices.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2020\/01\/31\/repeated-indexing-in-matlab\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[4],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/3541"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/users\/39"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/comments?post=3541"}],"version-history":[{"count":3,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/3541\/revisions"}],"predecessor-version":[{"id":3549,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/3541\/revisions\/3549"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=3541"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=3541"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=3541"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}