10
$\begingroup$

I have two plots, both with the exact same formatting (frame, text style, etc.). One of them has 2-digit values for the y axes, the other has scientific notation because the value are large. In addition, they can have a different number of lines for the Axes labels.

I set ImageSize->250, and the bounding boxes of the images (plots) are set to 250 pixels. Cool. Normally this is fine. However, when the two plots have different axes or labels, this results in:

ImageSize->250. Bounding boxes of images are the same

What I want is the actual plot area to be the same, without manually adjusting ImageSize for the 2nd image:

The Plot areas are the same size, but the bounding box for the entire image is different.

Notice how the labels make the bounding box grow outward, but the plot area size is the same (also in width, just not shown). In this particular example, the right image has ImageSize->280.

Does anyone know how to set the plot area size rather than the ImageSize?

EDIT 1:

@anononononomous mentioned a function to get the max padding size, and then apply it to each plot. This is getting closer! But it's clipping the FrameLabel:

(Also, sorry for adding more data, it doesn't change the question though).

anononononomous's solution

$\endgroup$
  • $\begingroup$ I believe GraphicsGrid will equalize the heights. $\endgroup$ – DavidC Dec 14 '12 at 20:10
  • $\begingroup$ I think, if you use the same values for the options ImageSize and ImagePadding in both plots, you should get the same plot area size in both. $\endgroup$ – kglr Dec 14 '12 at 20:44
  • $\begingroup$ @NasserM.Abbasi Correct, DavidCarraher's solution is not sufficient. kguler, That's getting closer. If you pad the images enough, then you can get the plot area sizes eqaul. However, you end up with a lot of extra space between images (if they're in a list, for example). $\endgroup$ – dthor Dec 14 '12 at 20:55
5
$\begingroup$

With fingers crossed that someone will come up with a less manual method, I suggest the following completely manual approach: use the same setting for ImageSize and ImagePadding in all the plots to get the plot area sizes equalized.

 bwc1 = BoxWhiskerChart[data, FrameTicks -> Automatic, 
  LabelStyle -> Green, FrameLabel -> {{Style["y axis", Bold, 14, Green], None}, 
  {Style["x axis", Bold, 14, Green], None}},
  ImageSize -> 300, ImagePadding -> {{85, 5}, {50, 5}}];
 bwc2 = BoxWhiskerChart[100 data, 
   PlotLabel -> Style["line 1\nline 2", Bold],
   FrameTicks -> Automatic, LabelStyle -> Directive[Bold, Blue],
   FrameLabel -> {{Style["y axis", Bold, 14], None}, 
    {Style["y axis", Bold, 14], None}},
   ImageSize -> 300, ImagePadding -> {{85, 5}, {50, 5}}];
 bwc3 = BoxWhiskerChart[100000 data, 
   PlotLabel -> Style["line 1\nline 2\nline 3", Bold, 24],
   FrameTicks -> Automatic, LabelStyle -> Directive[Bold, 16, Red],
   FrameLabel -> {{Style["y axis", Bold, 14], None}, 
      {Style["y axis", Bold, 14], None}},
  ImageSize -> 300, ImagePadding -> {{85, 5}, {50, 5}}];

you get the same plot area size for all three plots:

 Overlay[{bwc1, bwc2, bwc3}, Alignment -> {Right, Bottom}]

enter image description here

But ... "you end up with a lot of extra space between images":

 Grid[{{bwc1, bwc2, bwc3}}, Alignment -> Bottom]

enter image description here

If you wrap each plot in Framed and set the FrameMargins for each to get rid of the extra spaces on the left:

 fbwc1 = Framed[bwc1, FrameStyle -> None, FrameMargins -> {{-50, 0}, {0, 0}}];
 fbwc2 = Framed[bwc2, FrameStyle -> None, FrameMargins -> {{-40, 0}, {0, 0}}];
 fbwc3 = Framed[bwc3, FrameStyle -> None, FrameMargins -> {{0, 0}, {0, 0}}];

you get equal plot area sizes:

 Overlay[{fbwc1, fbwc2, fbwc3}, Alignment -> {Right, Bottom}]

enter image description here

and no extra spaces on the left:

 Grid[{{fbwc1, fbwc2, fbwc3}}, Alignment -> Bottom]

enter image description here

$\endgroup$
  • $\begingroup$ +1 nice use of negative frame margins $\endgroup$ – Mike Honeychurch Dec 14 '12 at 22:08
  • $\begingroup$ I'm not sure how you could automate this. It looks like a manual method to me ...but if someone is doing a lot of these they can presumably set up a template once and then use repeatedly. $\endgroup$ – Mike Honeychurch Dec 14 '12 at 22:09
2
$\begingroup$

As stated above you need to have the ImagePadding set the same for every image, you want to use the getMaxPadding function used in this post: Programmatically combine 2D contour plots with 1D projections

$\endgroup$
1
$\begingroup$

First, let's start with some box whisker charts:

data = RandomReal[10, {4, 20}];
bwc1 = BoxWhiskerChart[data,
    FrameLabel->{{Style["y axis",14], None}, {Style["x axis", 14], None}}
];
bwc2 = BoxWhiskerChart[100 data,
    FrameLabel->{{Style["y axis",16], None}, {Style["x axis", 26], None}},
    PlotLabel->Style["line 1\nline 2", 14]
];
bwc3 = BoxWhiskerChart[10^5 data, 
    FrameLabel->{{Style["y axis",14], None}, {Style["x axis", 14], None}},
    PlotLabel->Style["line 1\nline 2\nline 3", 24]
];

What happens when we try to use Row:

Row[{bwc1, bwc2, bwc3}]

enter image description here

Not very good. To fix this, the simplest approach is to use the undocumented syntax ImageSize -> Automatic -> width, which sets the PlotRange size to width. Also, include a BaselinePosition option so that the axes of each chart are lined up:

Row[{
    Show[bwc1, ImageSize -> Automatic -> 200, BaselinePosition -> Axis],
    Show[bwc2, ImageSize -> Automatic -> 200, BaselinePosition -> Axis],
    Show[bwc3, ImageSize -> Automatic -> 200, BaselinePosition -> Axis]
}]

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.