{"id":25,"date":"2006-03-01T06:33:49","date_gmt":"2006-03-01T11:33:49","guid":{"rendered":"https:\/\/blogs.mathworks.com\/loren\/?p=25"},"modified":"2016-07-28T14:13:13","modified_gmt":"2016-07-28T19:13:13","slug":"more-on-expansion-arrayfun","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/loren\/2006\/03\/01\/more-on-expansion-arrayfun\/","title":{"rendered":"More on expansion: arrayfun"},"content":{"rendered":"<p>Since there seems to be so much interest in the topic of going <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=23\">beyond scalar expansion<\/a>, it seems worth talking about yet some other ways to achieve the same goals.  I am very appreciative of the thoughtful comments we've received so far on this topic and I know we will be weighing this input carefully as we design how to move forward.\r\n<\/p>\r\n<p>\r\nSuppose we want to raise all the values in <kbd>x<\/kbd> to all the powers in <kbd>powers<\/kbd>, where both <kbd>x<\/kbd> and <kbd>powers<\/kbd> are vectors, like this:\r\n<\/p>\r\n<pre class=\"code\">\r\npowers = 1:3;\r\nx = (0:.1:.4)';\r\n<\/pre>\r\n<p>\r\nWe know from the <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=23\">last blog article<\/a>, we can achieve this by creating larger intermediate arrays like this, using Tony's trick (used for most of the work in <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/repmat.html\"><kbd>repmat<kbd><\/a>:\r\n<\/p>\r\n<pre>\r\nX = x(:,ones(size(powers,2),1))\r\nP = powers(ones(size(x,1),1),:)\r\n<\/pre>\r\n<pre>\r\nX =\r\n\r\n         0         0         0\r\n    0.1000    0.1000    0.1000\r\n    0.2000    0.2000    0.2000\r\n    0.3000    0.3000    0.3000\r\n    0.4000    0.4000    0.4000\r\n\r\nP =\r\n\r\n     1     2     3\r\n     1     2     3\r\n     1     2     3\r\n     1     2     3\r\n     1     2     3\r\n<\/pre>\r\n<p>\r\nand then we are ready to perform the desired calculation:\r\n<pre class=\"code\">\r\nq = X.^P\r\n<\/pre>\r\n<pre>\r\nq =\r\n\r\n         0         0         0\r\n    0.1000    0.0100    0.0010\r\n    0.2000    0.0400    0.0080\r\n    0.3000    0.0900    0.0270\r\n    0.4000    0.1600    0.0640\r\n<\/pre>\r\n<p>\r\nbut at the cost of 2 larger arrays, <kbd>X<\/kbd> and <kbd>P<\/kbd>, that we might not even need going forward.\r\n<\/p>\r\n<p>\r\nIn the absence of new operators in MATLAB 7, how might we solve this today without creating these temporary arrays and without using a <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/for.html\"><kbd>for<\/kbd><\/a> loop?  A new feature in R14sp3, <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/arrayfun.html\"><kbd>arrayfun<\/kbd><\/a> is a good candidate.  Here are two ways to achieve the same results using <kbd>arrayfun<\/kbd>, the first iterating calculating results for each value of <kbd>x<\/kbd> and the second, for each value of <kbd>powers<\/kbd>.  I am taking advantage of anonymous functions, new in MATLAB 7, to define the function I want to calculate, first as a function of <kbd>powers<\/kbd>, and second, as a function of the <kbd>x<\/kbd> values.\r\n<\/p>\r\n<pre class=\"code\">\r\npq = cell2mat(arrayfun(@(p)x.^p,powers,'uniformoutput',false));\r\nxq = cell2mat(arrayfun(@(x)x.^powers,x,'uniformoutput',false));\r\n<\/pre>\r\n<p>Before proceeding, let's just make sure we're getting the right answer!\r\n<\/p>\r\n<pre class=\"code\">\r\nisequal(xq,pq,q)\r\nans =\r\n\r\n     1\r\n<\/pre>\r\n<p>\r\nNow that we've taken care of checking for correctness, let's decipher what the statements mean.  Taking the final arguments to <kbd>arrayfun<\/kbd> first, I chose nonuniform output since for each value of my function, I calculate a vector of output values, not a single value.  This places outputs for each input value (in this case, the values in <kbd>powers<\/kbd>), into cells in a cell array.  \r\n<\/p>\r\n<p>\r\nThe first argument is an anonyous function, a function defined \"inline\" that takes its non-argument values from the workspace.  So the first function, <kbd>@(p)x.^p<\/kbd>, takes <kbd>x<\/kbd> from the workspace.  The function itself takes the values in <kbd>x<\/kbd> and raises them each to some value <kbd>p<\/kbd>, the function argument.  Then with the second input to <kbd>arrayfun<\/kbd>, we set the argument to be iterated over to <kbd>powers<\/kbd> from our workspace.\r\n<\/p>\r\n<p>\r\nFinally, since our output is now in a cell array, in this case with each cell containing equal numbers of elements, we convert the cell array to a numeric matrix using <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/cell2mat.html\"><kbd>cell2mat<\/kbd><\/a>.  \r\n<\/p>\r\n<p>\r\nWhich of the 2 methods using <kbd>arrayfun<\/kbd> is preferable?  Well, as is so often, that depends.  Since there's an intermediate cell array, we might want to minimize its size.  How large are typical sizes for the vectors <kbd>x<\/kbd> and <kbd>powers<\/kbd>?  If one is typically substantially larger than the other, we might want to <a href=\"https:\/\/www.mathworks.com\/help\/matlab\/ref\/profile.html\"><kbd>profile<\/kbd><\/a> the code, either from the command line or the desktop.  The profiler can help us make these tradeoffs.\r\n<\/p>\r\n<p>\r\nOnce again I ask for you to add your thoughts <a href=\"https:\/\/blogs.mathworks.com\/loren\/?p=25\">here<\/a>.  Thanks.\r\n<\/p>","protected":false},"excerpt":{"rendered":"<p>Since there seems to be so much interest in the topic of going beyond scalar expansion, it seems worth talking about yet some other ways to achieve the same goals.  I am very appreciative of the... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/loren\/2006\/03\/01\/more-on-expansion-arrayfun\/\">read more >><\/a><\/p>","protected":false},"author":39,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[10,7,6,12],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/25"}],"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=25"}],"version-history":[{"count":2,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/25\/revisions"}],"predecessor-version":[{"id":1792,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/posts\/25\/revisions\/1792"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/media?parent=25"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/categories?post=25"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/loren\/wp-json\/wp\/v2\/tags?post=25"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}