5
$\begingroup$

I have a dataset that has a number of groups with overlapping sets. There is a point in the group within the intersection of the sets that I want to highlight by placing a marker of that point between the sets in the group.

I want to do use BoxWhiskerChart to show the distribution of the groups and place the marker between the plots in the group. The problem is that I have not been able to figure out where the box plots will be centered in the chart. Or better the x-axis range that each box plot occupies. This is further complicated by the fact that the locations change significantly as the BarSpacing option changes.

Is there a way to get the x-axis range that each box plot occupies in a BoxWhiskerChart (or at least the centre of each box plot) as the BarSpacing option varies?

This is a reasonable example of the problem I am trying to solve. Notice how the highlighted points do not line appear between the group box plots and jump around as BarSpacing is changed. I'd really like to use the Method -> {"BoxWidth" -> "Scaled"} option but I can't even get the fixed width option to work yet.

(*group dataset*)
data = Table[RandomVariate[
  NormalDistribution[RandomInteger[5], 1.5], 100],{3}, {2}];
(*get intersections and point within intersection for example*)
minsAndMaxes = Map[{Min[#], Max[#]} &, data, {2}];
groupIntersections = 
  Map[IntervalIntersection[Interval@#[[1]], Interval@#[[2]]] &, 
  minsAndMaxes, {1}];
displayPoints = RandomReal[{Min[#], Max[#]}] & /@ groupIntersections;

(*Show issue with Epilog and BarSpacing in Manipulate*)
Manipulate[BoxWhiskerChart[data, 
  ChartLabels -> {{"2002", "2001", "2000"}, None}, 
  BarSpacing -> {within, between},
  Epilog -> {Green, Opacity[.6], PointSize[.02], 
    MapIndexed[
     Tooltip[Point[{First@#2 2 - .5, #1}], NumberForm[#1, {2, 1}]] &, 
      displayPoints]}], 
 {{within, Tiny}, {Tiny, Medium, Large}}, 
 {{between, Medium}, {Tiny, Medium, Large}}]

Thanks.

$\endgroup$

1 Answer 1

4
$\begingroup$

Not sure how you want to place the displaypoints relative to the boxes, but ... you can find the coordinates of the bounding boxes using the ChartElementFunction as follows:

Manipulate[Module[{boundingboxes = {}}, 
  Row[{BoxWhiskerChart[data, ChartStyle -> {Red, Purple}, ImageSize -> 400,
     BarOrigin -> barorigin, BarSpacing -> {within, between},
     ChartElementFunction -> ({Opacity[.3], Hue[RandomReal[]], 
         boundingboxes = Append[boundingboxes, #1]; 
         Rectangle @@ Transpose[#1], Opacity[1], 
         ChartElementDataFunction["GlassBoxWhisker"][##]} &), 
     Method -> {"BoxWidth" -> boxwidth}, 
     ChartLabels -> {{"2002", "2001", "2000"}, None}], 
    Panel[Grid[boundingboxes], "bounding boxes", Top]}, Spacer[10]]], 
   {{within, Tiny}, {Tiny, Medium, Large}}, 
   {{between, Medium}, {Tiny, Medium, Large}}, 
   {{boxwidth, "Scaled"}, {"Scaled", "Fixed"}},
   {{barorigin, Bottom}, {Bottom, Top, Left, Right}}]

enter image description here

Alternatively, you can use Reap/Sow combination:

Reap[BoxWhiskerChart[data, BarSpacing->{Tiny, Large}, Method->{"BoxWidth" -> "Scaled"},
   ChartElementFunction->((Sow[#1]; ChartElementDataFunction["GlassBoxWhisker"][##])&),
   ChartLabels -> {{"2002", "2001", "2000"}, None}]][[2,1]]

{{{0.045229, 0.949808}, {-3.38525, 4.19586}}, {{1.04027, 1.94485}, {-2.68183, 3.84264}}, {{2.98985, 3.89443}, {-3.25875, 4.67004}}, {{3.98489, 4.88947}, {-2.16572, 4.60291}}, {{5.93447, 6.83905}, {-4.05161, 4.48291}}, {{6.92951, 7.83409}, {-2.78972, 5.82866}}}

Update: Using the bounding box coordinates in Epilog:

Table[Labeled[Module[{boundingboxes = {}, xcoords = {}}, 
    bwc = BoxWhiskerChart[data, ChartStyle -> {Red, Purple}, 
      ImageSize -> 300, BarSpacing -> {within, between}, 
      ChartElementFunction -> ((boundingboxes = 
       Append[boundingboxes, #1]; ChartElementDataFunction["GlassBoxWhisker"][##]) &)];
    xcoords = Mean[{#[[1, -1]], #[[2, 1]]}] & /@ 
      Partition[boundingboxes[[All, 1]], 2]; 
    Show[bwc, Epilog -> {Green, Opacity[.6], PointSize[.02], 
       Tooltip[Point[#], NumberForm[#[[2]], {2, 1}]] & /@ 
        Transpose[{xcoords, displayPoints}]}]], 
   Row[{"{within, between} = {", within, ", ", between, "}"}], Top], 
   {within, {Tiny, Medium, Large}}, 
   {between, {Tiny, Medium, Large}}] // Grid[#, Dividers -> All] &

enter image description here

Note: For BarOrigin->Left and BarOrigin->Right we need to change Partition[boundingboxes[[All, 1]], 2] to Partition[boundingboxes[[All, 2]], 2] and Transpose[{xcoords, displayPoints}] to Reverse/@Transpose[{xcoords, displayPoints}].

$\endgroup$
4
  • $\begingroup$ Thanks for the info on the chart element functions. However, it appears that I can't use boundingboxes in the Epilog option to place my points at mid-way between the box plot regions as it shows as empty {} when referenced. Is there a way to get Epilog to see the filled boundingboxes? I used the following: Epilog -> {Green, Opacity[.6], PointSize[.02], MapIndexed[Tooltip[ Point[ {Mean[{boundingboxes[[First@#2 2 - 1, 1, 2]] , boundingboxes[[First@#2 2, 1, 1]]}], #1}], NumberForm[#1, {2, 1}]] &, displayPoints]} $\endgroup$
    – Edmund
    Mar 22, 2015 at 19:07
  • $\begingroup$ Edmund, please see the update. $\endgroup$
    – kglr
    Mar 22, 2015 at 20:55
  • $\begingroup$ Wow! Very, very nice. Thanks! $\endgroup$
    – Edmund
    Mar 22, 2015 at 22:54
  • $\begingroup$ @Edmund, my pleasure. Thank you for the accept. $\endgroup$
    – kglr
    Mar 22, 2015 at 23:31

Your Answer

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

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