1
$\begingroup$

Here is some sample data

m = {{0.658254, 1.04273, 0.15, 0.613587, 2}, {0.157981, 4.03653, 1.25, 
        0.437706, 1}, {0.149204, 1.65371, 2.72, 0.571777, 1}, {0.495885, 
        3.62412, 1.67, 0.00119993, 3}, {-0.149204, 2.23414, 200., 0.260858, 
        0}, {-0.50905, 2.98259, 200., 0.146681, 0}, {-0.662643, 1.60788, 
        21.77, 0.0305032, 1}, {0.539769, 0.385922, 0.33, 0.450807, 
        2}, {0.157981, 3.77687, 1.04, 0.584416, 1}, {-0.623147, 4.32675, 
        200., 0.173352, 0}};

A color code

getColor[m_List, i_Integer] := Module[{s = m[[i, 5]]}, 
Which[s == -1, White, s == 0, Blue, s == 1, Red, s == 2, Darker[Green],
      s == 3, Cyan]];

data = Table[{PointSize[0.004], getColor[m, i], Point[{m[[i, 1]], 
       m[[i, 2]]}]}, {i, 1, Length[m]}];

And finally we plot them

S0 = Graphics[data]

Graphics renders the data using dots with the predefined point size. How can I change the plot markers to small squares instead of dots? Of course, I should be able to control the size of the new plot markers.

EDIT

If I use @Andrew S method in a Show like

P0 = Show[S0, Axes -> False, Frame -> True, FrameLabel -> {"x", "y"}, 
     RotateLabel -> False, LabelStyle -> Directive[FontFamily -> "Helvetica", 20], 
     PlotRange -> All, AspectRatio -> 1, PlotRangeClipping -> True,
     PlotRangePadding -> 0, ImageSize -> 500]

then the squares become rectangles.

The output of the Graphics

enter image description here

And then the output of the Show

enter image description here

EDIT 2

@m_goldberg:

Test.nb

The final plot markers are much bigger than in Graphics, while some of them are cut in half at the borders.

$\endgroup$
4
  • $\begingroup$ Use a small image of a square, then draw image at the desired x,y positions, with possibly a displacement of -a/2,-a/2 to centralize. $\endgroup$ Commented Mar 4, 2016 at 16:31
  • 2
    $\begingroup$ It's a bit funny, because you are building the Graphics yourself and you're not using ListPlot. It is a very small step to use Rectangle instead of Point and I wonder why you haven't just tried that? $\endgroup$
    – halirutan
    Commented Mar 4, 2016 at 16:41
  • $\begingroup$ Dont actually know what you mean by "become rectangles". DO you mean that the markers are cropped on the border? $\endgroup$
    – Andrew S.
    Commented Mar 4, 2016 at 17:02
  • $\begingroup$ Oh, sorry, something overlapped on my side. That's all due to the AspectRatio thing. If you want to go this way, then you have to specify the correct ratio here for the markers. See my edit. $\endgroup$
    – Andrew S.
    Commented Mar 4, 2016 at 17:40

2 Answers 2

6
$\begingroup$

If you need Graphics (even though for this ListPlot will be better), then you can use

rectSize = 0.05;
data = Table[
   {
    getColor[m, i],
    Rectangle[{m[[i, 1]] - rectSize, 
      m[[i, 2]] - rectSize}, {m[[i, 1]] + rectSize, 
      m[[i, 2]] + rectSize}]
    },
   {i, 1, Length[m]}
   ];

To draw rectangles instead of points:

enter image description here

Or with ListPlot

markSize = 0.05;
ListPlot[
 Table[{{m[[i, 1]], m[[i, 2]]}}, {i, 1, Length[m]}],
 PlotMarkers -> Table[
   {Graphics[{getColor[m, i], Rectangle[{-1, -1}, {1, 1}]}], markSize},
   {i, 1, Length[m]}
   ]
 ]

For this:

enter image description here

EDIT:

To fix the ratio problem after "post-rationing" the whole graphics object

yR = Max[m[[All, 2]]] - Min[m[[All, 2]]];
xR = Max[m[[All, 1]]] - Min[m[[All, 1]]];
rectSize = 0.05;
data = Table[
   {getColor[m, i], 
    Rectangle[{m[[i, 1]] - rectSize*xR/yR, 
      m[[i, 2]] - rectSize}, {m[[i, 1]] + rectSize*xR/yR, 
      m[[i, 2]] + rectSize}]},
   {i, 1, Length[m]}
   ];
$\endgroup$
3
  • $\begingroup$ Please, see my edit. $\endgroup$
    – Vaggelis_Z
    Commented Mar 4, 2016 at 16:55
  • $\begingroup$ Please, see my second edit. $\endgroup$
    – Vaggelis_Z
    Commented Mar 4, 2016 at 17:19
  • $\begingroup$ By the way, the solution with ListPlot is extremely slow when the data are huge (let's say 100000 elements). $\endgroup$
    – Vaggelis_Z
    Commented Mar 4, 2016 at 17:44
5
$\begingroup$

First let's simplify your code so it will be easier to make the adjustment you are asking for.

m = {{0.658254, 1.04273, 0.15, 0.613587, 2}, {0.157981, 4.03653, 1.25,
     0.437706, 1}, {0.149204, 1.65371, 2.72, 0.571777, 1}, {0.495885, 
     3.62412, 1.67, 0.00119993, 3}, {-0.149204, 2.23414, 200., 
     0.260858, 0}, {-0.50905, 2.98259, 200., 0.146681, 0}, {-0.662643, 
     1.60788, 21.77, 0.0305032, 1}, {0.539769, 0.385922, 0.33, 
     0.450807, 2}, {0.157981, 3.77687, 1.04, 0.584416, 1}, {-0.623147, 
     4.32675, 200., 0.173352, 0}};

colors = <|-1 -> White, 0 -> Blue, 1 -> Red, 2 -> Darker[Green], 3 -> Cyan|>;
pts = {colors[#[[5]]], AbsolutePointSize[8], Point[#[[1 ;; 2]]]} & /@ m;

pts

Now, let's replace pts with a marker generating function that will accept any graphics object and make markers scaled to a specified fraction of the graphics viewport.

markers[graphic_, scale_, data_] := 
  Inset[
    Graphics[{colors[#[[5]]], graphic}], 
    #[[1 ;; 2]], {.5, .5}, Scaled[scale]]& 
  /@ data

Now we can reproduce your point image with

Graphics[markers[Disk[], .07, m]]

and also produce square markers this way

Graphics[markers[Rectangle[], .08, m]]

or this way

Graphics[markers[RegularPolygon[4], .08, m]]

sqrs

and even have pentagon markers.

Graphics[markers[RegularPolygon[5], .1, m]]

penta

Update

Versions of Mathematica too old to have associations can use a list of rules to set the colors.

colorRules = {-1 -> White, 0 -> Blue, 1 -> Red, 2 -> Darker[Green], 3 -> Cyan};
markers[graphic_, scale_, data_] :=
  Inset[
    Graphics[{#[[5]] /. colorRules, graphic}], 
    #[[1 ;; 2]], {.5, .5}, Scaled[scale]]& 
  /@ data

Update 2

You only need to make some minor adjustments. Reduce the marker scale factor, add PlotRangePadding and remove PlotRangeClipping.

Show[Graphics[markers[RegularPolygon[4], .025, m]], 
  Axes -> False, 
  Frame -> True, 
  FrameLabel -> {"x", "y"}, 
  RotateLabel -> False, 
  LabelStyle -> Directive[FontFamily -> "Helvetica", 20], 
  PlotRange -> All, 
  AspectRatio -> 1, 
  PlotRangePadding -> .15, 
  ImageSize -> 500]

show

$\endgroup$
14
  • $\begingroup$ When I copy paste your code I get an error in colors regarding < |. I use v9.0. $\endgroup$
    – Vaggelis_Z
    Commented Mar 4, 2016 at 17:23
  • $\begingroup$ @Vaggelis_Z. What error? I don't have V9, so I can not test with it. Please report what error you are getting. $\endgroup$
    – m_goldberg
    Commented Mar 4, 2016 at 17:29
  • $\begingroup$ Since @Vaggelis is on version 9, he won't have Association[] available. He can do something like #[[5]] /. {-1 -> White, 0 -> Blue, 1 -> Red, 2 -> Darker[Green], 3 -> Cyan} tho. $\endgroup$ Commented Mar 4, 2016 at 17:31
  • $\begingroup$ @m_goldberg I get the following: Syntax::tsntxi: "colors=<|-1->White,0->Blue,1->Red,2->Darker[Green],3->Cyan|>;" is incomplete; more input is needed., while the < | and | > at the beginning and at the end of the expression are highlighted. $\endgroup$
    – Vaggelis_Z
    Commented Mar 4, 2016 at 17:33
  • $\begingroup$ @J.M. That's too bad, because an association is very suited to his problem. I'll write a version using rules and update. $\endgroup$
    – m_goldberg
    Commented Mar 4, 2016 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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