19
$\begingroup$

I have an array of $(x,y,z)$ triples (array dimensions: N x 3), from which I can make a 2D scatterplot of $(x,y)$ values:

t = Table[{Sin[i], Cos[i], i}, {i, 0, 2 \[Pi], N[\[Pi]/20]}];
ListPlot[t[[All, 1 ;; 2]]]

Now, I want to color each point according to its $z$ value. I can find how to do so by creating a series of Disks and putting them all into a Graphics, but then I have to take of absolutely all the formatting. Yet, I can't see how to leverage ListPlot options, such as ColorFunction, to achieve my goal. What would you suggest?

$\endgroup$
2

6 Answers 6

12
$\begingroup$

Since your data is essentially 3D, I'll offer another solution which does not require you to roll your own, and is closer to what you intended (i.e., use built-in and change the ColorFunction).

The approach is simple — plot the data in 3D, explicitly color the points according to the $z$-value and view the resulting plot along the $z$-axis (which makes it a 2D plot).

ListPointPlot3D[t, ColorFunction -> (Hue@#3 &), ViewPoint -> {0, 0, ∞}, Axes -> {True, True, False}]

The advantage of this over ListPlot is that you can easily associate the $z$-value of each $(x,y)$ pair in the color function since we're actually plotting the triplet $(x,y,z)$, whereas in ListPlot, once you split the list into a list of $(x,y)$ pairs and $z$-values, you'll have to resort to mapping and combining several of them with Show (or other ways), which is clumsy. That said, were I to do this, I would roll my own, since it offers greater control and customizability.

$\endgroup$
6
$\begingroup$

A direct way to "leverage the options" (without otherwise exploiting some alternative workaround to ListPlot) reorganizes the points, using List /@ to make each one a separate part of the plot whose style can be separately specified in parallel with the points list:

ListPlot[List /@ t[[All, 1 ;; 2]], 
 PlotStyle -> ({PointSize[0.033], Hue[#/(2 \[Pi]), 4/5, 4/5]} & /@ t[[All, 3]]), 
 AspectRatio -> 1]

Figure

(The parentheses around the target of PlotStyle -> are essential.)

A (small) disadvantage is apparent: any value of PlotStyle intended to be common to all points, such as their size, has to be part of the specification for each point. The construct here--mapping a list of styles via {...}& /@ over the z-values--is a clean way to write the common style specifications just once each.

$\endgroup$
3
  • $\begingroup$ Love that one! And somewhat sad not to have thought of it… $\endgroup$
    – F'x
    Mar 20, 2013 at 14:36
  • $\begingroup$ Is this solution acceptable? Points left and right from (0,1) are close to the max and min value of the z-coord. According to the color scale, their z-coord. is almost the same. $\endgroup$
    – DeeDee
    Apr 4, 2013 at 13:32
  • $\begingroup$ That's just an over-reading of the colors, DeeDee: with the hue scale, colors at the two ends are close to each other. Use a different color ramp if you like. $\endgroup$
    – whuber
    Apr 4, 2013 at 14:47
4
$\begingroup$

If you just care about the options used in your ListPlot, why don't you extract them and use it in your custom made Graphics?

t = Table[{Sin[i], Cos[i], i}, {i, 0, 2 \[Pi], N[\[Pi]/20]}];
opts = AbsoluteOptions[ListPlot[t[[All, 1 ;; 2]]]];

Graphics[{PointSize[.02], {ColorData["Rainbow", Last[#]/(2 Pi)], 
     Point[Most[#]]} & /@ t}, Sequence @@ opts]

Mathematica graphics

$\endgroup$
0
4
$\begingroup$

Maybe a little faster:

Block[{a, vc, pts},
 a = Range[0., 2 Pi, Pi/20.];
 pts = Transpose[{Sin[a], Cos[a]}];
 vc = ColorData["Rainbow", #] & /@ Rescale[a];
 Graphics[{[email protected], Point[pts, VertexColors -> vc]}, Axes -> 1]]

enter image description here

$\endgroup$
2
  • $\begingroup$ +1 It's about six times faster--potentially a good solution for large lists where the more complex options of ListPlot and its kin are unneeded. $\endgroup$
    – whuber
    Mar 20, 2013 at 14:39
  • $\begingroup$ Excellent suggestion, I did not know that VertexColors works with Point and I had performance problems before because I had to break up data into several Points just for colouring. $\endgroup$
    – Szabolcs
    Mar 20, 2013 at 14:46
4
$\begingroup$

You can wrap the elements of t with Style:

t = Table[{Sin[i], Cos[i], i}, {i, 0, 2 \[Pi], N[\[Pi]/20]}];

ListPlot[Style[#[[;; 2]], PointSize[.02], ColorData["Rainbow"][#[[3]]/Max[t[[All, 3]]]]]&
   /@ t, AspectRatio -> 1]

enter image description here

Or use BubbleChart:

BubbleChart[t, ColorFunction -> (ColorData["Rainbow"][#3] &),
  BubbleSizes -> {0.02, 0.02}, Axes -> True, Frame -> False]

enter image description here

$\endgroup$
2
$\begingroup$

This is very hacky but it makes direct use of ColorFunction in ListPlot

t = Table[{Sin[i], Cos[i], i}, {i, 0, 2 \[Pi], N[\[Pi]/20]}];
counter = 1;
ListPlot[t[[All, 1 ;; 2]], Joined -> True, 
  PlotStyle -> PointSize -> 0.02, 
  ColorFunction -> 
   Function[{x, y}, 
    col = ColorData["Rainbow"][t[[counter, 3]]/(2*Pi)]; 
    counter = counter + 1; col]] /. Line -> Point

pretty points

$\endgroup$

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