# Mapping a function over n levels

I want to map a function over a matrix of rank n, for example:

PercentChange[v_?VectorQ] := Differences@v/Most@v*100
PercentChange[v_] := Map[PercentChange, v, {Length@Dimensions@v-1}]

m = N@Range@10;

PercentChange /@ {m, {m, m}, {{m, m}, {m, m}}}


This works as expected.

Now, as a lazy beginner, I thought that I could get rid of the duplicate definition of "PercentChange" and simply state:

PercentChange[v_] := Map[PercentChange, v, {Length@Dimensions@v - 1}]


However, to my disappointment this didn' t function because "Map" doesn't accept a level {0} parameter:

Map[Differences@m/Most@m, m, {0}]*100


On the other hand, this functions in all cases:

Percent2[v_] := Map[Differences@#/Most@# &, v, {Length@Dimensions@v-1}]*100


How would you write this without duplication and slot-notation?

Your assertion that Map does not accept a levelspec of {0} is incorrect:

Map[f, bar[1, 2, 3], {0}]

f[bar[1, 2, 3]]


Percent2[v_] := Map[Differences@#/Most@# &, v, {Length@Dimensions@v-1}]*100


Which duplication are you referring to, and why don't you like Slot notation?

Anyway, if you are merely looking for a different style perhaps:

fn[v_?VectorQ] := Differences@v / Most@v * 100
fn[a_?ArrayQ]  := fn /@ a

fn[{a, b, c}]
fn[{{a, b, c}, {q, r, s}}]

{(100 (-a + b))/a, (100 (-b + c))/b}

{{(100 (-a + b))/a, (100 (-b + c))/b}, {(100 (-q + r))/q, (100 (-r + s))/r}}


Also ArrayDepth[v] - {1} is a little cleaner than {Length @ Dimensions @ v - 1}.

Although far less clean in my opinion, we could also take advantage of the second parameter of Differences, and use a substitute for Most, to perform this operation without an explicit Map.

fn2[a_?ArrayQ] :=
Differences[a, depth] / Part[a, ##] * 100 & @@ (depth /. {0 -> All, 1 -> ;; -2})
]


Test:

m = N @ Range @ 10;
lists = {m, {m, m}, {{m, m}, {m, m}}};
fn /@ lists === fn2 /@ lists

True

• (1) Just try "Map[Differences@m/Most@m*100, m, {0}]" with the above definition of "m" - it doesn't function. (2) With "duplication" I meant the initial definition of "PercentChange" (lines 1 and 2 of my question). – eldo May 16 '14 at 21:01
• @eldo The problem with Map[Differences@m/Most@m*100, m, {0}] is that the first argument is not a function. – Mr.Wizard May 16 '14 at 21:05
• Thanks for clarifying this to me ;) – eldo May 16 '14 at 22:04
• @eldo The "wink" suggests to me that you say that sarcastically; if that is the case I genuinely don't know what you're looking for and I am trying to be helpful. If however I misunderstand you are welcome. Either way I will attempt to answer more questions if I am able to understand what you are asking. – Mr.Wizard May 17 '14 at 2:50
• The "wink" was a polite smile – eldo May 17 '14 at 7:10