Re: Can I Map[] this code?
- To: mathgroup at smc.vnet.net
- Subject: [mg95987] Re: Can I Map[] this code?
- From: Jean-Marc Gulliet <jeanmarc.gulliet at gmail.com>
- Date: Sat, 31 Jan 2009 06:43:17 -0500 (EST)
- Organization: The Open University, Milton Keynes, UK
- References: <glvk8r$e47$1@smc.vnet.net>
In article <glvk8r$e47$1 at smc.vnet.net>, Andreas <aagas at ix.netcom.com> wrote: > As I have more experience with procedural programming, I'd like to better > understand how to use Mathematica's capabilities to do operations to or > mapping functions to lists. > > As an example I have two lists of lists: > > values = {{1, 1, 1, 1}, {1.03, 1.01, .90, .87}, {1.15, .987, 1.1, 1}, {.925, > 1.1, 1.03, 1}} > > points = { > {0.0842331, 0.445974, 0.0762394, 0.393553}, > {0.0507857, 0.316297, 0.217557, 0.415361}, > {0.0772796, 0.715707, 0.0966355, 0.110378}, > {0.407287, 0.0992621, 0.294046, 0.199405}, > {0.115973, 0.483231, 0.125979, 0.274817}, > {0.0819106, 0.64151, 0.0656714, 0.210908}, > {0.0240671, 0.164786, 0.230353, 0.580795}, > {0.0402821, 0.582524, 0.131371, 0.245823}, > {0.374207, 0.242838, 0.0277256, 0.355229}, > {0.130812, 0.459584, 0.331101, 0.078503} > } > > I have a named function: > > function2[point_, value_] := If[value == 0, 0, 1 + ((value - 1) * point)] > > That I want to apply across the elements in the list in a function like the > following: > > function1[points_, values_] := > Table[ > Sum[ > Sum[ > function2[points[[j, k]], values[[i, k]]], > {k, 1, Length[values[[1]]]} > ], {j, 1, Length[points]} > ]/Length[points], > {i, 1, Length[values]} > ] > > function1 works OK. I just wonder if I can do this kind of calculation more > elegantly using something like the Map[] function and how I would do it in a > situation like the above. > > I also have a concern about processing speed as the lengths of both lists of > lists can get quite large. > > The larger question goes to this. In what kind of situations should one use > iterative functions like Table[], Sum[], etc and when does one better use > Map[] or other such functions? What advantages and disadvantages does either > approach have over the other? > > Any guidance much appreciated. FWIW, My philosophy could be summarize as follows: "Write short functions and combine them with high level constructs," i.e. think much less in terms of computer sciences (3d-array, loop, indices, summation,...) and much more in terms of mathematical operations (tensors, ---generalized--- inner product, mean,...). Therefore, your code could be written as f2 = Function[{p, v}, Boole[v != 0]*(1 + (v - 1)*p)]; f3 = Function[{p, v}, Inner[f2, p, v, Plus]]; f4 = Function[{p, v}, Mean[(f3[#1, v] & ) /@ p]]; f1[p_, v_] := (f4[p, #1] & ) /@ v Now, have you bothered to *describe* what you try to achieve in words (using higher level concepts than loops and indices :-), an even better and to the point solution could have been written. Nevertheless, the above code works, as you can see below, and is much faster than the original solution (and this can be improved). In[1]:= values = {{1, 1, 1, 1}, {1.03, 1.01, .90, .87}, {1.15, .987, 1.1, 1}, {.925, 1.1, 1.03, 1}}; In[2]:= points = {{0.0842331, 0.445974, 0.0762394, 0.393553}, {0.0507857, 0.316297, 0.217557, 0.415361}, {0.0772796, 0.715707, 0.0966355, 0.110378}, {0.407287, 0.0992621, 0.294046, 0.199405}, {0.115973, 0.483231, 0.125979, 0.274817}, {0.0819106, 0.64151, 0.0656714, 0.210908}, {0.0240671, 0.164786, 0.230353, 0.580795}, {0.0402821, 0.582524, 0.131371, 0.245823}, {0.374207, 0.242838, 0.0277256, 0.355229}, {0.130812, 0.459584, 0.331101, 0.078503}}; In[3]:= f2 = Function[{p, v}, Boole[v != 0]*(1 + (v - 1)*p)]; f3 = Function[{p, v}, Inner[f2, p, v, Plus]]; f4 = Function[{p, v}, Mean[(f3[#1, v] & ) /@ p]]; f1[points_, values_] := (f4[points, #1] & ) /@ values f1[points, values] Out[7]= {4, 3.9551, 4.03137, 4.03591} In[8]:= function2[point_, value_] := If[value == 0, 0, 1 + ((value - 1)*point)] function1[points_, values_] := Table[ Sum[ Sum[ function2[points[[j, k]], values[[i, k]]], {k, 1, Length[values[[1]]]} ], {j, 1, Length[points]} ]/Length[points], {i, 1, Length[values]} ] function1[points, values] Out[10]= {4, 3.9551, 4.03137, 4.03591} Regards, --Jean-Marc