Re: Using Select within Map
- To: mathgroup at smc.vnet.net
- Subject: [mg71815] Re: Using Select within Map
- From: "Philipp" <Philipp.M.O at gmail.com>
- Date: Thu, 30 Nov 2006 06:05:06 -0500 (EST)
- References: <ekh70s$s7p$1@smc.vnet.net>
Mark, I had also found pure functions with Slot[] as formal parameters pretty daunting. The way I learned to use them was, at first, through applying pure function with named parameters and by "bottom-up" refinement of my expressions. Let's apply the methodology to your problem, but first let's put some meat into your list, In[1]:= SeedRandom[12]; {mPairs, nLists} = {4, 5} z = Table[Table[{Random[Real], Random[Integer, {1, 20}]}, {mPairs}], {nLists}] Out[2]= {4, 5} Out[3]= {{{0.732816, 9}, {0.610675, 16}, {0.00875556, 18}, {0.635694,14}}, {{0.859504, 6}, {0.457415, 10}, {0.726225, 10}, {0.613483, 8}}, {{0.618313, 6}, {0.287895, 15}, {0.210696, 7}, {0.914434, 12}}, {{0.280328, 12}, {0.0245793, 5}, {0.957919, 1}, {0.844565, 17}}, {{0.638937, 20}, {0.7423, 1}, {0.15219, 3}, {0.560185, 17}}} Further, let's choose the first sub-list of pairs and name it t, and choose the values for a & b In[4]:= t = First[z] {a, b} = {0.5, 0.7} Out[4]= {{0.732816, 9}, {0.610675, 16}, {0.00875556, 18}, {0.635694, 14}} Out[5]= {0.5, 0.7} Now, Select[list, crit] applies crit to each element of list, in our case to each pair of numbers. We want to test only the first element of each pair, In[6]:= Select[t, Function[pair, a < First[pair] < b]] Out[6]= {{0.610675, 16}, {0.635694, 14}} The above is of course the exact functional equivalent to In[7]:= Select[t, a < First[#] < b &] Out[7]= {{0.610675, 16}, {0.635694, 14}} The argument pair (or # (Slot[1])) has meaning only within the scope of argument 2 of Select, i.e., Select[t, here]. In other words, only the Select function sees it and knows how to interpret it. As I understand, you want to calculate a mean value for the selected pairs here. This could be done with another pure function that wraps the Select statement, but to keep it simple let's define it as named function and call it mean In[8]:= Clear[mean]; mean[{}] := {} mean[{pairs : {_?NumberQ, _?NumberQ}}] := pairs mean[pairs_] := Apply[Plus, pairs]/Length[pairs] We have a statement that calculates a mean (whatever it means) for a single row of number pairs. In[12]:= mean[Select[t, Function[pair, a < First[pair] < b]]] mean[Select[t, a < First[#] < b &]] Out[12]= {0.623184, 15} Out[13]= {0.623184, 15} Now we need to apply it to every element of the initial list (remembering that the pure function at argument 2 of Extract is invisible to anything but Extract). Let's look at an example of Map applicable to the situation Map[f, {a, b, c}] -> {f[a], f[b], f[c]} Now, In[14]:= Clear[f]; Map[f, z] Map[f[#] &, z] Out[15]= {f[{{0.732816, 9}, {0.610675, 16}, {0.00875556, 18}, {0.635694, 14}}], f[{{0.859504, 6}, {0.457415, 10}, {0.726225, 10}, {0.613483, 8}}], f[{{0.618313, 6}, {0.287895, 15}, {0.210696, 7}, {0.914434, 12}}], f[{{0.280328, 12}, {0.0245793, 5}, {0.957919, 1}, {0.844565, 17}}], f[{{0.638937, 20}, {0.7423, 1}, {0.15219, 3}, {0.560185, 17}}]} Out[16]= {f[{{0.732816, 9}, {0.610675, 16}, {0.00875556, 18}, {0.635694, 14}}], f[{{0.859504, 6}, {0.457415, 10}, {0.726225, 10}, {0.613483, 8}}], f[{{0.618313, 6}, {0.287895, 15}, {0.210696, 7}, {0.914434, 12}}], f[{{0.280328, 12}, {0.0245793, 5}, {0.957919, 1}, {0.844565, 17}}], f[{{0.638937, 20}, {0.7423, 1}, {0.15219, 3}, {0.560185, 17}}]} which is exactly what we would want if f was our function. Since t is equal to z[[1]], i.e., the statements mean[Select[t, ...]] will achieve what we want if we substitute z[[1]], then z[[2]], ... in the place of t, let's rewrite the statements as pure functions that would operate on each single row of z (i.e., on z[[1]], z[[2]], ...) just as f does, In[17]:= Function[rowOfPairs, mean[Select[rowOfPairs, Function[pair, a< First[pair] < b]]]] mean[Select[#, a < First[#] < b &]] & Out[17]= Function[rowOfPairs, mean[Select[rowOfPairs, Function[pair, a< First[pair] < b]]]] Out[18]= mean[Select[#1, a < First[#1] < b &]] & We can test them by applying t as arguments In[19]:= Function[rowOfPairs, mean[Select[rowOfPairs, Function[pair, a< First[pair] < b]]]] [t] mean[Select[#, a < First[#] < b &]] & [t] Out[19]= {0.623184, 15} Out[20]= {0.623184, 15} Both functions a now ready to be mapped onto each element of z, i.e., In[21]:= Map[Function[rowOfPairs, mean[Select[rowOfPairs, Function[pair, a < First[pair] < b]]]], z] Map[mean[Select[#, a < First[#] < b &]] &, z] Out[21]= {{0.6231844789732769, 15}, {0.6134834543719954, 8}, {0.6183128646046326, 6}, {}, {0.5995611645768835, 37/2}} Out[22]= {{0.6231844789732769, 15}, {0.6134834543719954, 8}, {0.6183128646046326, 6}, {}, {0.5995611645768835, 37/2}} I sincerely hope the above explanation will be of some help. As I've tried to demonstrate the trick is to build your expressions "bottom-up". Cheers, Philipp. Mark Teagarden wrote: > Hi, > > I have a data set which comprises several paired lists, like so (I apologize > if the tabs do not come out correctly in your mail client): > > x = > { > { > { , }, > { , }, > { , } > }, > { > { , }, > { , }, > { , } > }, > { > { , }, > { , }, > { , } > } > } > > What I would like to do is to select from each of those paired lists, only > those pairs where the first value in the pair falls within some specified > range, and then obtain a mean. This would be simple enough if I was > operating on a single paired list, for example: > > Select[x[[1]],a < #[[1]] < b&] > > However, I would like to Map over x so that I would end up with means for > each of the level 1 lists within x; therein lies the problem. Both Map and > Select use the Slot operator (#), and I don't know how to distinguish > between the slot operator used by Map, and the slot operator used by Select: > > Select[#,a < #[[1]] < b&]/@x > > Or if you prefer: > > Map[Select[#, a < #[[1]] < b&,x] > > This problem has been plaguing me for some time, and if I could punch > through it I would be very happy indeed. Any ideas? I have had no luck > looking through the archives or the Help Browser. On a similar note, I > would eventually like to modify this solution so that the criteria, a and b, > could vary with each level 1 list in x, but one thing at a time... > > Thanks in advance, > Mark > > -- > Mark A. Teagarden, Ph.D. > University of Texas at San Antonio > Department of Biology > One UTSA Circle > San Antonio, TX 78249