MathGroup Archive 2006

[Date Index] [Thread Index] [Author Index]

Search the Archive

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


  • Prev by Date: Re: Re: Re: Arithmetic Puzzle (so simple it's hard)
  • Next by Date: Re: funny question
  • Previous by thread: Re: Using Select within Map
  • Next by thread: Unexpected warning with ArcTan