5
$\begingroup$

Consider the following BarChart:

BarChart[{{1, 2, 3}, {None, 2, None}, {1, None, 5}},
         ChartLegends -> {"A", "B", "C"},
         ChartLabels -> {{"X", "Y", "Z"}, None},
         LabelingFunction -> (Placed[Row[{"", #}], Bottom] &),
         BarSpacing -> None, AxesLabel -> "l"]

How can the empty bars be removed to save space with the appropriate coloring/labels maintained?

enter image description here

$\endgroup$
1

3 Answers 3

5
$\begingroup$

You can use the metadata form of BarChart's data elements, $\text{form}_i\to m_i$, to specify the bar colour when a category is omitted. You do have to specify the colours in ChartStyle as well.

data = {{1,2,3},{None,2,None},{1,None,5}};

BarChart[
 First@MapThread[
   Thread@*Rule,
   {
    {data /. None -> Nothing},
    {Pick[{Orange, Brown, Blue}, #, True] & /@ 
      Map[NumericQ, data, {2}]}
    }, 2]
 ,
 ChartStyle -> {Orange, Brown, Blue},
 ChartLegends -> {"A", "B", "C"},
 ChartLabels -> {{"X", "Y", "Z"}, None}, 
 LabelingFunction -> (Placed[Row[{"", #}], Bottom] &), 
 BarSpacing -> None, AxesLabel -> "l"]

enter image description here

Hope this helps.

$\endgroup$
2
$\begingroup$

I think you want to use RectangleChart for this purpose. First you need to make a new data set which contains the widths of each bar. Here's the data manipulation:

data = {{1,2,3},{None,2,None},{1,None,5}};
data2 = data /. None->0
data3 = Table[{HeavisideTheta[data2[[i, j]] - 0.1], data2[[i, j]]},
{i, 1, 3}, {j, 1, 3}];

The HeavisideTheta function gives each bar unit width unless it was originally "None"

RectangleChart[data3, ChartLegends -> {"A", "B", "C"}, 
ChartLabels -> {{"X", "Y", "Z"}, None}, 
LabelingFunction -> (Placed[Row[{"", #[[2]]/.(0)->""}], Bottom] &), 
BarSpacing -> None, AxesLabel -> "l"]

EDIT: Following @Kuba's suggestion, the list manipulation can be more elegantly done using

datanew = Map[{1, #} /. {_, None} -> {0, 0} &, data, {2}]

...and inserting this into the first argument of the RectangleChart function above

$\endgroup$
3
  • $\begingroup$ /. (0) -> "" () are missing $\endgroup$
    – Kuba
    Dec 2, 2015 at 9:43
  • $\begingroup$ Thanks @Kuba. Actually, it seems either /.(0)->"" or /. 0->"" [i.e. with a space] works. I appreciate this is a bit of a hack. I'm sure there's a more elegant way to do this. $\endgroup$
    – PatrickS
    Dec 2, 2015 at 9:46
  • $\begingroup$ That's nice solution, consider Map[{1, #} /. {_, None} -> {0, 0} &, data, {2}]. $\endgroup$
    – Kuba
    Dec 2, 2015 at 9:47
0
$\begingroup$

Color each data point using Style and remove the non-numeric data points:

data = {{1, 2, 3}, {None, 2, None}, {1, None, 5}};
colors = ColorData[59, "ColorList"][[;; Length@data[[1]]]];
styleddata = Style @@@ (Thread[{#, colors}]) & /@ data /. Style[ None, __] :> (## &[]);

BarChart[styleddata, ChartLegends -> SwatchLegend[59, {"A", "B", "C"}],
 ChartLabels -> {{"X", "Y", "Z"}, None},
 LabelingFunction -> (Placed[Row[{"", #}], Bottom] &), BarSpacing -> None]

enter image description here

SeedRandom[1]
data2 = RandomChoice[{1, 1, 1, 1, 1, 4} -> {1, 2, 3, 4, 5, None}, {5, 6}];
colors = ColorData[54, "ColorList"][[;; Length@data2[[1]]]];
styleddata = Style @@@ (Thread[{#, colors}]) & /@ data2 /. Style[ None, __] :> (## &[]);

BarChart[styleddata, 
 ChartLegends -> SwatchLegend[54, CharacterRange["A", "Z"][[;; Length @ data2[[1]]]]],
 ChartLabels -> {{"X", "Y", "Z", "W", "V"}, None},
 LabelingFunction -> (Placed[Row[{"", #}], Bottom] &), BarSpacing -> None]

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.