0
$\begingroup$

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?

$\endgroup$
3
$\begingroup$

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]]

For your second definition:

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] :=
 With[{depth = PadLeft[{1}, ArrayDepth[a]]},
   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
$\endgroup$
  • $\begingroup$ (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). $\endgroup$ – eldo May 16 '14 at 21:01
  • $\begingroup$ @eldo The problem with Map[Differences@m/Most@m*100, m, {0}] is that the first argument is not a function. $\endgroup$ – Mr.Wizard May 16 '14 at 21:05
  • $\begingroup$ Thanks for clarifying this to me ;) $\endgroup$ – eldo May 16 '14 at 22:04
  • $\begingroup$ @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. $\endgroup$ – Mr.Wizard May 17 '14 at 2:50
  • $\begingroup$ The "wink" was a polite smile $\endgroup$ – eldo May 17 '14 at 7:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.