The syntax of the PLOT statement in PROC BOXPLOT is
PLOT analysis-var * group-var (block-vars);
The procedure always uses the group-var to form the groups and determine the order in which the boxplots are arranged. The block-vars are only applied after the grouping is done and are used to label consecutive groups once they have been plotted.
A character group-var can be in any order, but a numeric group-var must be sorted in increasing numeric order. Even when block-vars are used, numeric groups must still be sorted for the entire plot, not within each block.
The block-vars can be either character or numeric, there is no sorting requirement, and the values of the block-vars should be the same for all the observations within a value of the group-var.
Sometimes only one block label is displayed even though there are multiple blocks in the data. The following describes how this can happen. Suppose your data set contains a group-var, GROUP, a block-var, BLOCK, and an analysis-var, Y. For example:
Group Block y
----- ----- -
1 1 #
1 1 #
2 1 #
2 1 #
1 2 #
1 2 #
2 2 #
2 2 #
where # represents numeric values, and you expect the following box plot
![]() |
If GROUP is a numeric variable and you specify:
proc boxplot;
plot y * Group(Block);
run;
this causes
ERROR: The values of the subgroup variable GROUP are not sorted in increasing order in the data set <data set name>.
If you then specify:
proc sort; by Group; run; proc boxplot; plot y * Group(Block); run;
the resulting data set and plot look like the following:
Group Block y
----- ----- -
1 1 #
1 1 #
1 2 #
1 2 #
2 1 #
2 1 #
2 2 #
2 2 #
![]() |
This is the correct chart for the given code and data, since the GROUP variable forms the groups and the first value of the BLOCK variable labels the blocks of consecutive groups.
The first graph above shows the correct use of block-vars and that is with groups nested within blocks. When you sort by GROUP you are incorrectly nesting blocks within groups.
When the group-var is a numeric variable, you can have this arrangement of groups and blocks:
![]() |
The group-var must be a character variable to have this arrangement:
![]() |
To get this last chart when GROUP is numeric, create a character version of the group-var using a DATA step and use it in the PLOT statement. For example, if the original data set, A, contains a numeric variable, GROUP, the following statements create a character version of it named CharacterGroup and use it to produce the desired chart:
data a; set a; CharacterGroup=put(Group, 1.); run; proc boxplot; plot y * CharacterGroup(Block); run;
![]() |
A similar situation arises when a whole group within a block is missing. For example, the following depicts a data set that has no CharacterGroup=1 within Block=2:
CharacterGroup Block y
-------------- ----- -
1 1 #
1 1 #
2 1 #
2 1 #
2 2 # No CharacterGroup=1 within Block=2
2 2 #
1 3 #
1 3 #
2 3 #
2 3 #
These statements
proc boxplot;
plot y * CharacterGroup(Block) / blockpos=3;
run;
produce the following plot
![]() |
It appears that CharacterGroup=2, Block=2 is missing. Again, this plot is correct because the boxes are formed from the group-var and all of the first set of consecutive observations where CharacterGroup=2 will form a single box. If you want consecutive group-var values that are the same to form separate boxes, you can insert a missing value in between observations where a new box is to start and use the MISSBREAK option on the PLOT statement. For example, with the following data and code
CharacterGroup Block y
-------------- ----- -
1 1 #
1 1 #
2 1 #
2 1 #
. . .
2 2 #
2 2 #
1 3 #
1 3 #
2 3 #
2 3 #
proc boxplot;
plot y * CharacterGroup(Block) / blockpos=3
missbreak;
run;
you get the desired result:
![]() |