Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

This question already has an answer here:

calibData = { {200, 10}, {100, 20} }

MapAt[N, MapAt[Log10, calibData, {;; , 1}], {;; , 1}]

I want to apply a base 10 Log to the first element of each tuple. Then the output should be displayed as a floating point number.

This bit of code does the job, but it is ugly and its hard to understand what it is doing. Is there a better way of completing this task?

share|improve this question

marked as duplicate by Artes, halirutan, Michael E2, m_goldberg, R. M. Oct 9 '13 at 2:44

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

This is using the solution of that post. I think this was a new issue I had. The motivation behind the post was to understand functional style programming to a greater extent. – olliepower Oct 8 '13 at 22:52
Have no idea why this post got downvoted... – Leo Fang Oct 9 '13 at 0:28
up vote 2 down vote accepted

If you have a large amount of calibData, then preserving packed arrays can greatly improve speed. Convert it all to Reals and then apply logarithm.

calibData = 10 RandomInteger[{1, 20}, {10^6, 2}];

Transpose @ {Log10 @ #[[1]], #[[2]]} &@ Transpose @ N @ calibData; // AbsoluteTiming
(* {0.098568, Null} *)

Transpose @ {Log10 @ N @ calibData[[All, 1]], N @ calibData[[All, 2]]}; // AbsoluteTiming
(* {0.106482, Null} *)

MapAt[Log10, N@calibData, {All, 1}]; // AbsoluteTiming
(* {1.525485, Null} *)

The second components of calibData get converted to Real in this process. If you need them to be integers, you might use Round if the integers are not too large. Otherwise, you can hope that the performance with unpacked arrays is acceptable.

Compared with unpacked:

Transpose @ {Log10 @ N @ calibData[[All, 1]], calibData[[All, 2]]}; // AbsoluteTiming
(* {0.369981, Null} *)

MapAt[N @ Log10[#] &, calibData, {All, 1}]; // AbsoluteTiming
(* {8.740113, Null} *)

The arrays will be unpacked in these cases because the numbers are not all the same type (some Real, some Integer).

share|improve this answer

This question has probably been asked here before, or something similar. I can't find it yet but try this:

MapAt[N@Log10[#] &, calibData, {All, 1}]

OR via pattern-matching:

calibData /. {x_, y_} :> {N@Log10[x], y}

Using Apply:

{N @ Log10 @ #1, #2} & @@@ calibData
share|improve this answer

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