15
$\begingroup$

Consider this example:

data = Table[{x, x^2}, {x, -2, 2, 0.1}];
ListPlot[Style[{#1, #2}, PointSize[Abs[#2]/50], Hue[#2]] & @@@ data]

the results from V9 and V10 are as follows:

V9 enter image description here

V10 enter image description here

It looks like two layers of points have been generated in V10 (one with style and the other without style).

Any explanation for this and how to make the result of V10 similar to that of V9?

Thanks

$\endgroup$
  • $\begingroup$ I notice that you have not Accepted an answer to this question. Are you unsatisfied by any of the explanations and work-arounds given? $\endgroup$ – Mr.Wizard Feb 12 '16 at 12:52
  • $\begingroup$ @Mr.Wizard I almost forgot about this question :) $\endgroup$ – Algohi Feb 12 '16 at 15:11
  • $\begingroup$ Well, thank you. I wasn't meaning to complain, just checking in. When I don't Accept any answer it's usually because, no matter how good the existing ones are, I am hoping for something more. For example people tried darn hard for me on (1137) but a convenient platform-independent solution still seems slightly out of reach. $\endgroup$ – Mr.Wizard Feb 12 '16 at 20:19
7
$\begingroup$

You are correct that the points are being rendered twice, as can be seen with:

data = Table[{x, x^2}, {x, -1.3, -0.4, 0.1}];
g1 = ListPlot[Style[{#1, #2}, PointSize[Abs[#2]/50], Hue[#2]] & @@@ data];

First[g1]

enter image description here

Note that there is a Point expression with all the points followed by individually styled Point expressions which render in color in this output.

A bit of spelunking shows that Style is but one of many wrappers handled by ListPlot. When non-numeric data is passed this function is called:

Charting`ListPlotParser

With a definition including:

  ...
    Charting`ParserDump`initPList[model,SystemWrappers];
    Charting`ParserDump`initPList[model,ApplicationWrappers];
    Charting`ParserDump`initPList[model,MetaWrappers];
    Charting`ParserDump`initPList[model,ModelWrappers];
    Charting`ParserDump`initPList[model,QuantityWrappers];
    Charting`ParserDump`initPList[model,ErrorWrappers];
  ...

Later the function Charting`ParserDump`stripWrappers is used, from which we may find the definitions:

Definition @@ Names["Charting`ParserDump`$*WrapperPattern"]

Charting`ParserDump`$ApplicationWrapperPattern =
  Charting`Highlighted | Labeled | Charting`Tweaked | Legended | Style | Placed

Charting`ParserDump`$ErrorWrapperPattern = PlusMinus | Charting`ErrorBar

Charting`ParserDump`$MetaWrapperPattern = Alternatives[Rule]

Charting`ParserDump`$ModelWrapperPattern = EventData | WeightedData

Charting`ParserDump`$SystemWrapperPattern =
  Annotation | Button | EventHandler | Hyperlink | Mouseover | PopupWindow | StatusArea | Tooltip

And later still the styling is apparently added back with something like:

System`ProtoPlotDump`modelData$15013["ApplicationWrappers", "Add", {2} -> {Style, 
  RGBColor[1, 0, 0]}]

The point of all this rambling is that it seems the wrapper system has been greatly extended to handle many different heads, including ones that are intended to add to rather than replace plot points. Because of this it seems an edge case was created where the persistence of the original points is undesirable.

The complexity of this system makes it difficult to propose a general solution. If all points are going to be Style wrapped then you can simply remove the first Point object as Michael shows, or set the PlotStyle to PointSize[0] as Brett shows, but if only some of your points are Style wrapped this will not work as intended.

I cannot yet imagine how this will interact with the many different wrappers recognized by ListPlot but for the case of Style alone I think it is appropriate to filter out any points from the first Point expression that also appear later in a Style expression:

fixStyleWrappers =
  {{a___, {b___, Point[p : {__}]}, c___}, sty : {__}} :>
   With[{filtered = 
      DeleteCases[p, 
       Alternatives @@ Cases[sty, Style[{Point[{d : {_, _}}]}, ___] :> d, -1]]},
     {{a, {b, Point @ filtered}, c}, sty}
   ];

Example:

ListPlot[{0.1, Style[0.3, Red, AbsolutePointSize[5]], 0.5}, 
  PlotStyle -> AbsolutePointSize[12]] /. fixStyleWrappers

enter image description here

$\endgroup$
7
$\begingroup$

If you look closely at V9 you'll see that it does the same thing, except that the points are darker, smaller, and generally not as obvious:

enter image description here

The easiest way to get rid of this is to make the points very small:

ListPlot[..., PlotStyle -> PointSize[0]]

enter image description here

$\endgroup$
  • $\begingroup$ So is it correct that two layers of points are plotted? if yes can you elaborate on that in you answer. $\endgroup$ – Algohi Sep 29 '14 at 20:50
  • $\begingroup$ I would prefer that they weren't duplicated, but they are probably serving a purpose that isn't obvious. I believe they only show up with Style and perhaps a few other wrappers. $\endgroup$ – Brett Champion Sep 29 '14 at 20:56
  • $\begingroup$ @Brett Do you feel that this behavior is not a bug? It seems like one, though quite understandable. (Assuming my analysis is correct.) Should I tag the question with bugs or not? $\endgroup$ – Mr.Wizard Sep 29 '14 at 22:42
5
$\begingroup$

The problem is with PlotThemes plotting points below your "styled" points. You can override this with PlotTheme->"None" (throws an error but works), or you can just use Graphics and skip the whole PlotTheme business anyway:

Graphics[Style[Point[{#1, #2}], PointSize[Abs[#2]/50], Hue[#2]] & @@@ 
 data, Axes -> True, AspectRatio -> 1/GoldenRatio]

enter image description here

$\endgroup$
  • $\begingroup$ PlotTheme -> "Classic" is the best way to get back to V9 behavior. $\endgroup$ – Brett Champion Sep 29 '14 at 20:42
4
$\begingroup$

The OP's analysis of what it looks like seems to be exactly right. I think it must be a bug. A (sort of ugly) workaround is to removed the unstyled points:

ListPlot[Style[{#1, #2}, PointSize[Abs[#2]/50], Hue[#2]] & @@@ 
   data] /. Point[{{_, _}, {_, _} ..}] -> {}

Mathematica graphics

$\endgroup$
3
$\begingroup$

In version 9, PlotStyle->PointSize[0] or BaseStyle->PointSize[0] does not get rid of those dots. They become visible when you set the opacity to less then 1.

data = Table[{x, x^2}, {x, -2, 2, 0.1}];
ListPlot[Style[{#1, #2}, PointSize[Abs[#2]/50], Directive[Opacity[.5], Hue[#2]]] & @@@ data, 
 PlotStyle -> PointSize[0]]

enter image description here

Two additional work-arounds are (1) to set the value of the PlotMarkers option to an empty String or an empty Graphic, or (2) use PlotStyle -> Opacity[0]:

ListPlot[Style[{#1, #2}, PointSize[Abs[#2]/50], 
    Directive[Opacity[.5], Hue[#2]]] & @@@ data, PlotMarkers -> ""]
(* or PlotMarkers ->Graphics[{}]  or PlotStyle->Opacity[] *)

enter image description here

$\endgroup$
2
$\begingroup$

So many great answers here, just thought I'd throw out there that another way to get a plot like OP's is to use the function BubbleChart

BubbleChart[Table[{x, x^2, x^2/5}, {x, -2, 2, 0.1}],
 ColorFunction -> (Hue[#2] &),
 ColorFunctionScaling -> False,
 BubbleSizes -> {.1^2, 2^2}/30,
 AspectRatio -> 1/2]

enter image description here

$\endgroup$

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.