# How to speed up ListPlot when each point has its own color

I have a list of (x,y) points I would like to plot with each point a specific color. ListPlot is substantially slower when I assign each point a color than when I use the default single color for each point.

Any idea on how to speed up?

Below is test code where I have assigned one of four colors randomly. Note the timing.

Thanks.

n = 10^4;
locs = Table[{RandomReal[] , RandomReal[]} , n];
c = RandomChoice [ {Red, Green, Blue, Black} , n];
t0 = TimeUsed[];
p1 = ListPlot[locs, ImageSize -> 800];
t1 = TimeUsed[];
p2 = ListPlot[List /@ locs, ImageSize -> 800, PlotStyle -> c];
t2 = TimeUsed[];
Print [ "All same color = ", t1 - t0 , " cpu seconds." ];
Print["Each point its own color = " , t2 - t1 , " cpu seconds." ];


All same color = 0.115 cpu seconds. Each point its own color = 7.015 cpu seconds

• Note: you can use Timing (or AbsoluteTiming) to measure how much time it takes to execute some command. For example, p1 = ListPlot[locs, ImageSize -> 800]; // AbsoluteTiming yields 0.1 seconds and p2 = ListPlot[List /@ locs, ImageSize -> 800, PlotStyle -> c]; // AbsoluteTiming yields 9.3 seconds. No need to use that t0 = TimeUsed[]; trickery. – AccidentalFourierTransform Apr 23 '18 at 1:15
• What about Graphics[Point[locs, VertexColors -> c], Options@ListPlot]? What you lose is automatic PointSize[] determination.... – Michael E2 Apr 23 '18 at 1:28
• FWIW the trick of coloring the data mathematica.stackexchange.com/a/80403/2079 turns out to be extremely slow.. – george2079 Apr 23 '18 at 16:04

VertexColors is an efficient way. You can use it with p1 as follows (it adds very little time):

p4 = p1 /. Point[p_] :> Point[p, VertexColors -> c]; // AbsoluteTiming
p4

(*  {0.000087, Null}  *)


You can also apply it directly in Graphics, although you lose the automatic PointSize[] control:

Graphics[Point[locs, VertexColors -> c], Options@ListPlot]


How about this. Not fancy but fast. Make sure n is divisible by 4 which is # of colors.

n = 10^4;
locs = RandomReal[{0, 1}, {n, 2}];
locs2 = Partition[locs, n/4];
ListPlot[locs]; // AbsoluteTiming // First


0.107778

Show[ListPlot[locs2[[1]], PlotStyle -> {Red}],
ListPlot[locs2[[2]], PlotStyle -> {Green}],
ListPlot[locs2[[3]], PlotStyle -> {Blue}],
ListPlot[locs2[[4]], PlotStyle -> {Black}]]; //
AbsoluteTiming // First


0.158271

n = 10^4;
locs = Table[{RandomReal[], RandomReal[]}, n];
c = RandomChoice[{Red, Green, Blue, Black}, n];
p2 = ListPlot[List /@ locs, ImageSize -> 800, PlotStyle -> c]; //
AbsoluteTiming // First


7.67799

• Since the OP raises the specific question of timing, perhaps you ought to time this and compare? – Michael E2 Apr 23 '18 at 1:42
• Sure, I'll be edit it. – OkkesDulgerci Apr 23 '18 at 1:43
• Thanks for the reminder about AbsoluteTiming. As usual, there;'s always a more elegant way to learn. The Partitioning works but I should have been clearer that in the actual application, the colors have meaning as opposed to the random assignment I made for the example. In other words, each point is one of four colors for a specific reason so I need to carry that info along. – jmm Apr 23 '18 at 2:31
• note this approach can be automated as ListPlot[#[[All, All, 1]],PlotStyle -> #[[All, 1, 2]]] &@GatherBy[Transpose[{locs, c}], #[[2]] &] (with c as in original post ) – george2079 Apr 23 '18 at 17:07
• And with @george2079 's code, it's not dependent on a prescribed structure and correspondence of the data and colors, but seems more fitting with the OP's original formulation of the problem. – Michael E2 Apr 24 '18 at 13:29