Re: Map vs. Table
- To: mathgroup at smc.vnet.net
- Subject: [mg75412] Re: Map vs. Table
- From: Szabolcs <szhorvat at gmail.com>
- Date: Sat, 28 Apr 2007 06:04:53 -0400 (EDT)
- Organization: University of Bergen
- References: <f0sfrs$ncb$1@smc.vnet.net>
zac wrote:
> Dear Group,
>
> consider a set of data (y values):
>
> data = Table[i*j, {i, 5}, {j, 10}]
>
> I want to label each Integer with an x value:
>
> label := Table[{i, #} & /@ data[[i]], {i, Length[data]}]
>
It is better to use Set instead of SetDelayed here, otherwise the Table
will be re-evaluated every time you use label. (Use = instead of :=)
> I've understand that list creation is much faster with Map than with
> Table.
It is generally a good idea to avoid explicitly indexing lists when not
necessary. But here you *do* need the index i, as a label.
> Is there an effective way to convert the Table to Map in the label
> function (either with nested Map or to incorporate the Table function
> into the Map)?
>
> Would it be really faster for very large datasets than with Table?
>
> thanks
>
> Istvan Zachar
>
There are many ways to do this calculation. If you want to avoid
indexing data, then you either need to use MapIndexed or pre-generate
the labels.
I tried these:
In[46]:=
data=Table[i j, {i, 2000}, {j, 2000}];
In[47]:=
Timing[label=Table[{i,#}& /@ data[[i]], {i, Length[data]}];]
Out[47]=
{1.031 Second,Null}
In[48]:=
Timing[label=MapIndexed[First@Outer[List, #2, #1]&, data];]
Out[48]=
{1.407 Second,Null}
In[49]:=
Timing[label=MapIndexed[Thread[Append[#2, #1]]&, data];]
Out[49]=
{1.609 Second,Null}
In[50]:=
Timing[label=Thread/@Transpose[{Range@Length@data, data}];]
Out[50]=
{1.422 Second,Null}
You must not take these timings too seriously (the times are too short,
and inconsistent with every run), though they suggest that using Table
is faster then the rest.
The problem is that with larger data matrices only Table works, all the
others run out of memory! I guess that this is because data is stored as
a packed array and the Table approach is the only one that doesn't break
this internal representation.
In[51]:=
<<Developer`
PackedArrayQ[data]
Out[52]=
True
PackedArrayQ[label] is only true when label is generated by Table.
So I tried to come up with an approach that is similarly simple to
Table, and did this:
label = Transpose@Inner[List, Range@Length@data, data, List];
But to my greatest disappointment it turned out to be the slowest of all
(and also breaks the packed array representation).
So probably the Table solution is the best to use (because it needs the
least memory). It is also the most straightforward and most readable way
of doing this. It seems that a strictly functional style is not always
the best way do things in Mathematica.
Can anyone come up with a good way of solving this problem without
indexing data?
Szabolcs