7
$\begingroup$

I have a ListPlot function

lp2 := 
 ListPlot[{#} & /@ #1, 
   PlotMarkers -> {Graphics@{Rectangle[]}, #2}, 
   AspectRatio -> 1, 
   AxesOrigin -> {0, 0}, 
   PlotRange -> All, 
   PlotStyle -> Hue /@ RandomReal[1, {Length@#1}], 
   Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, Line@#1}, 
   Frame -> True, 
   FrameTicks -> All
 ] &

which attempts to add a unit rectangle centered on each point however this relies on having constant axis to scale the unit rectangle to fit the axis. When PlotRange->All the axis ignores the aspect ratio and pretty much everything else. Is it possible to alter this behavior or scale the rectangle to the size of the axis chosen by Mathematica?

$\endgroup$
9
  • $\begingroup$ "unit rectangle" - I don't understand; as a rectangle has width and height, there should be two parameters, no? What dimensions were you expecting for these rectangles? $\endgroup$ Commented Feb 15, 2012 at 11:46
  • $\begingroup$ @J.M. I assume he means a unit square: the default shape of Rectangle[]. $\endgroup$
    – Mr.Wizard
    Commented Feb 15, 2012 at 12:01
  • $\begingroup$ Ooops, yeah, a unit square is defined as Rectangle[] in mathematica sorry for the confusion. $\endgroup$ Commented Feb 15, 2012 at 12:15
  • $\begingroup$ @user Please review my answer below and tell me if that is what you want. If it is, I will also suggest a way to do this bypassing ListPlot and using Graphics primitives directly. $\endgroup$
    – Mr.Wizard
    Commented Feb 15, 2012 at 12:19
  • 1
    $\begingroup$ Looks like this is related to this SO question and my answer there. to change the markers from squares to rectangles with aspect ratio that matches the aspect ratio of the plot, you need to use a second argument to the Graphics that define the plot markers: instead of Graphics@{Rec..} use Graphics[{Rectangle[]},AspectRatio->.5 (say). $\endgroup$
    – kglr
    Commented Feb 15, 2012 at 12:38

3 Answers 3

8
$\begingroup$

Depending on your needs is may be both simpler and more flexible to bypass ListPlot completely and do this directly in Graphics. Here is a simple example:

dat = RandomReal[11, {15, 2}];

Graphics[{
   {Hue @ RandomReal[], Rectangle[# - 0.5]} & /@ #,
   {GrayLevel[.3], PointSize[.02], Point@#, Thick, Line@#}
  },
  AspectRatio -> 0.5,
  Frame -> True
] & @ dat

Mathematica graphics

$\endgroup$
0
7
$\begingroup$

Try your plot followed by:

/. Inset -> (Inset[#, #2, Automatic, 1] &)

Like:

lp2[args] /. Inset -> (Inset[#, #2, Automatic, 1] &)

This works by post-processing the Graphics object that in generated by ListPlot. The function Infix is used to place the PlotMarkers. Normally it is using without the size argument to keep the plot markers an absolute size. You want the markers unit size which can be done with:
Inset[_, _, _, 1].

You should get something like this:

Mathematica graphics

You can of course include this in your definition of lp2 but I am not sure of your syntax so I did not want to make the change myself.


You can specify an explicit aspect ratio for the PlotMarkers while using this, e.g. (in the definition of lp2):

PlotMarkers -> {Graphics[{Rectangle[]}, AspectRatio -> 0.5]}

Mathematica graphics

If you need help rolling this into your function let me know.


As a side note you do not need SetDelayed (:=) when defining a pure function (&); use Set (=).

$\endgroup$
5
$\begingroup$

Although I'm a bit late in answering this, I thought it's worth pointing out for completeness that there's actually a built-in function that is basically designed to do exactly what this question asks for: ErrorListPlot as shown below where I just modify the given definition slightly in the first few lines:

Needs["ErrorBarPlots`"]

lp3 = ErrorListPlot[{#, ErrorBar[{}]} & /@ #1, 
    ErrorBarFunction -> 
     Function[{coords, errs}, {EdgeForm[Orange], LightOrange, 
       Rectangle[coords - #2/2, coords + #2/2]}],
    AspectRatio -> 1, AxesOrigin -> {0, 0}, 
    PlotStyle -> Hue /@ RandomReal[1, {Length@#1}], 
    Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, 
      Line@#1}, Frame -> True, FrameTicks -> All] &;

The function allows you to specify the option ErrorBarFunction, and there is an example in the documentation showing how a rectangle can be constructed based on the errors in the data. Here I adapted that example to use a constant error in both horizontal and vertical directions.

Here is a set of test data - using differently scaled real numbers instead of integers:

data = {30, 10} # & /@ RandomReal[1, {15, 2}]

(*
==> {{15.0817, 8.63497}, {29.1274, 4.68834}, {3.86173, 
  2.3385}, {14.3022, 0.452592}, {2.81023, 9.56299}, {27.9932, 
  1.82105}, {1.35937, 0.0468926}, {9.20839, 2.01352}, {2.8601, 
  7.20318}, {11.0419, 1.71997}, {19.9694, 6.43578}, {10.9362, 
  6.84062}, {6.76464, 8.23109}, {21.5031, 4.1016}, {28.083, 6.58259}}
*)

lp3[data, 1]

ErrorListPlot

Edit

Since the original question had variable colors, I should also add that to my solution. Here I color the edge according to the distance from the origin, and the inside according to the angle with the $x$ axis:

lp4 = ErrorListPlot[{#, ErrorBar[{}]} & /@ #1, 
    ErrorBarFunction -> 
     Function[{coords, errs}, {EdgeForm[Hue[Norm[coords]/20]], 
       Hue[2/Pi ArcTan @@ coords], 
       Rectangle[coords - #2/2, coords + #2/2]}], AspectRatio -> 1, 
    AxesOrigin -> {0, 0}, 
    Epilog -> {GrayLevel[.3], PointSize[.02], Point@#1, Thick, 
      Line@#1}, Frame -> True, FrameTicks -> All] &;

lp4[data, 2]

colored boxes

$\endgroup$

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.