How to transform the $y$ values in a list of $(x,y)$ pairs [duplicate]

How can I transform

data = {{1, 0}, {0, 1}, {1, 1}}

to

{{1, f}, {0, f}, {1, f}}

This is similar to Applying a function to the second element of a list and another way to do this mapping of a two argument function, but it's not the same question

• MapAt[f, data, {All, -1}]
– Kuba
Jun 30 '16 at 13:02
• This is almost certainly a duplicate isn't it? Jun 30 '16 at 15:55

data = {{1, 0}, {0, 1}};
data /. {x_?NumericQ, y_?NumericQ} :> {x, f@y}

and

data = {{1, 0}, {0, 1}};
MapAt[f, data, {All, 2}]

will fix the problems mentioned by masterxilo's answer

• MapAt[f, data, {All, -1}] works as well. Jun 30 '16 at 13:11
• @J.M. yep, I changed that because it was identical to Kuba's comment. Jun 30 '16 at 13:12
{#1, f@#2} & @@@ data

But we can also generalize MapAt to do the job: Note that

MapAt[f, data, {1, 2}] === {{1, f}, {0, 1}, {1, 1}}

So we can use

MapAtP[f_, expr_, positionPattern_] := MapIndexed[
If[MatchQ[#2, positionPattern], f@#1, #1] &, expr, Infinity]

MapAtP[f, data, {_, 2}]

Aside

David Wagner's “Power programming with Mathematica”

Are you interested in purchasing David Wagner's "Power programming with Mathematica"?

mentions the following idiom as "a more Mathematica-like way" to transform on the values of a list of (x,y) data points.

data = {{1, 0}, {0, 1}, {1, 1}};
data /. {x_, y_} -> {x, f@y}
(**)
{{1, f}, {0, f}, {1, f}}

But it fails with lists of length exactly 2:

data = {{1, 0}, {0, 1}};
data /. {x_, y_} -> {x, f@y}
(**)
{{1, 0}, f[{1, 0}]}
• your replacement rule should be ...f@y Jun 30 '16 at 13:09