cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Check out the JMP® Marketplace featured Capability Explorer add-in
Choose Language Hide Translation Bar
Byron_JMP
Staff
Graph Builder Bar Graph Label Offset

Graph builder can display value labels on bar graphs, unfortunately, if data is also plotted on the bar graph, the labels are completely obscured.  

 

Byron_JMP_0-1722467443810.png

 

Fortunately it is relatively easy to manually reposition the labels. Getting alignment correct is a wee bit tricky, and doing this more than once is relatively frustrating.  Even editing the graph script to get alignments correct is tedious after the second or third iteration of a graph.  With a little JSL magic we can find the frames and bar segments and automatically adjust the label off sets.

 

In the script below an example data table is opened, and then a graph script is run, followed by some formatting instructions.

To use this script, either substitute in your data table reference or uncomment the "dt=current data table();" line to let the script run agains the current table. The graph builder script is an example, you use RTM>Save Script> to Clipboard to get your graph builder script and then paste it in place of the example.

 

names default to here(1);
//paste your data table reference here, or just use the current data table.
dt=Open( "$SAMPLE_DATA/Big Class.jmp" );
//dt=current data table();

obj=dt<<
//Paste your graph builder script here
Graph Builder(
	Size( 518, 470 ),
	Show Control Panel( 0 ),
	Variables( X( :age ), Y( :height ) ),
	Elements(
		Bar(X,Y,Legend( 4 ),
			Error Interval( "Standard Error" ),
			Label( "Label by Value" )),
		Points( X, Y, Legend( 5 ) )),
	SendToReport(
		Dispatch( {}, "400", ScaleBox,
			{Legend Model(4,
				Properties(0,{Fill Color( 0 ), Fill Pattern( "none" )},Item ID( "Mean", 1 )))}))
);
// End of graph builder script.

//Make a reference for the bar chart segments
fbi= N Items( (obj << xpath( "//FrameBox" )) );
for (ii=1, ii<=fbi, ii++,
frame = Report( obj )[FrameBox( ii )];
seg = (frame << Find Seg( "Bar Seg" ));

//Get variable used for the X axis	
vars=obj<< Get Variables();
xx=vars[1];xx[1];
//Find the number of bars (or levels used to make bars)
Summarize( levels = By( eval(xx[1])));
Eval List( levels );
//Build an expression to change the offset
qq=expr(set label offset());
for (i=0, i<=nitems(levels)*fbi, i++,	//Note there is a multipler, *fbi. This assumes each level is the same for each frame. Its kind of sloppy, might need to just replace it with a fixed value.
	rr={};
	insert into (rr, i); 	//This is the Bar number, starts with zero
	insert into (rr,i); 	//This is the x offset, which is the same as the bar number
	insert into(rr, 10);	//This is the Y offset
	insert into (qq, (rr)); 
	
);
//Make magic happen
eval(substitute(expr(seg<<qq), expr(qq), name expr(qq)));
);//end of ii for next loop

 

In a previous blog post I described the steps and included an automation script for adding error bars with annotations to "Dynamite" plots, bar charts with an interval line. https://community.jmp.com/t5/Byron-Wingerd-s-Blog/One-Way-ANOVA-Figure-for-Scientists/ba-p/265156

Last Modified: Aug 1, 2024 9:34 AM
Comments
hogi
Level XII

hi @Byron_JMP , nice trick. very useful.

alternatively one could add the labels to a second bar graph element:

dt=Open( "$SAMPLE_DATA/Big Class.jmp" );
Graph Builder(
	Size( 563, 522 ),
	Summary Statistic( "Median" ),
	Graph Spacing( 4 ),
	Variables( X( :age ), Y( :height ) ),
	Elements(
		Bar( X, Y, Legend( 4 ), Error Interval( "Standard Error" ) ),
		Points( X, Y, Legend( 5 ) ),
		Bar( X, Y, Legend( 6 ), Bar Style( "Float" ), Label( "Label by Value" ) )
	)
);

I often have a related issue: no space for horizontal labels:

hogi_0-1722489363458.png

Is there a workaround via JSL to rotate the labels?


Byron_JMP
Staff

It sounds like you would like to have the labels rotated like this:

Byron_JMP_0-1722518734255.png

I wouldn't have tried without your question.  There is some obscure JSL that lets you set the font properties AND the angle. Honestly I've never seen this done before, and it looks pretty fantastic.
The JSL is this: Set Font( "", 18, "", 90 ).  The font is "", the size is 18 points, the formatting is "", and the angle is 90. In the scripting index the example has the font specified and the formatting specified, but replacing those with, "", appears to use the default.  Changing the angle to -90 makes the text read bottom to top.

 

 

 

names default to here(1);
//paste your data table reference here, or just use the current data table.
dt=Open( "$SAMPLE_DATA/Big Class.jmp" );
//dt=current data table();

obj=dt<<
//Paste your graph builder script here
Graph Builder(
	Size( 518, 470 ),
	Show Control Panel( 0 ),
	Variables( X( :age ), Y( :height ) ),
	Elements(
		Bar(X,Y,Legend( 4 ),
			Error Interval( "Standard Error" ),
			Label( "Label by Value" )),
		Points( X, Y, Legend( 5 ) )),
	SendToReport(
		Dispatch( {}, "400", ScaleBox,
			{Legend Model(4,
				Properties(0,{Fill Color( 0 ), Fill Pattern( "none" )},Item ID( "Mean", 1 )))}),
							Dispatch( {}, "Graph Builder", FrameBox,
			{DispatchSeg(
				BarSeg( 1 ),
				Set Font( "", 18, "", 90 )
				
			)}
		)
				)
);
// End of graph builder script.

//Make a reference for the bar chart segments
fbi= N Items( (obj << xpath( "//FrameBox" )) );
for (ii=1, ii<=fbi, ii++,
frame = Report( obj )[FrameBox( ii )];
seg = (frame << Find Seg( "Bar Seg" ));

//Get variable used for the X axis	
vars=obj<< Get Variables();
xx=vars[1];xx[1];
//Find the number of bars (or levels used to make bars)
Summarize( levels = By( eval(xx[1])));
Eval List( levels );
//Build an expression to change the offset
qq=expr(set label offset());
for (i=0, i<=nitems(levels)*fbi, i++,	//Note there is a multipler, *fbi. This assumes each level is the same for each frame. Its kind of sloppy, might need to just replace it with a fixed value.
	rr={};
	insert into (rr, i); 	//This is the Bar number, starts with zero
	insert into (rr,i); 	//This is the x offset, which is the same as the bar number
	insert into(rr, 10);	//This is the Y offset
	insert into (qq, (rr)); 
	
);
//Make magic happen
eval(substitute(expr(seg<<qq), expr(qq), name expr(qq)));
);//end of ii for next loop

 

hogi
Level XII

cool! amazing!
thanks.

hogi
Level XII

Hm ...
I just wondered how I managed to get the labels away from the top of the graph  ... without any JSL.

-> Ah: JMP17 !

So, as another workaround for "Bar Graph Label Offset" :
switch back to JMP 17 and user age on the x axis an as Overlay:

// JMP 17!
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
dt << new column("one", set each value(1));
dt << Graph Builder(
	Variables( X( :age ), Y( :height ), Overlay( :age ), Color( :one ) ),
	Elements(
		Bar(
			X,
			Y,
			Legend( 1 ),
			Summary Statistic( "Mean" ),
			Error Interval( "Standard Error" ),
			Label( "Label by Value" )
		),
		Points( X, Y, Overlay( 0 ), Legend( 2 ) )
	),
	SendToReport(
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				1,
				Properties(
					0,
					{Fill Color( 0 ), Fill Pattern( "none" )},
					Item ID( "1", 1 )
				)
			), Legend Model(
				2,
				Properties( 0, {Line Color( 0 )}, Item ID( "1", 1 ) )
			)}
		)
	)
);

 

hogi_3-1722544453746.png


disadvantages:

- there seems to be a bug with the error bars which got fixed with JMP18.

- none of the other cool JMP 18 features.

hogi
Level XII

Thinking of all the JMP users without JSL experience...
Actually, there should be a control for the placement of the labels right in the GUI.

Ah, there is a wish from 2020 from @shampton82 with this idea:

Graph builder bar chart data label control 

 

shampton82
Level VII

Thanks for linking this blog and the wish list item @hogi !  While it is great that we can add in so much functionality with JSL, one of the most embarrassing things when showing off JMP is not being able to do very basic things with chart customizations that users can do in excel (and are so use to, it blows their mind you can't do it in JMP easily).  

 

@Byron_JMP Please work with the JMP team to make this great customization become non-JSL based!

 

Steve

hogi
Level XII

agree.

hogi
Level XII

I just found out what's the difference between JMP 17 and JMP18:
one gets the label centered in JMP18 when switching to Stacked mode.

Unfortunately, this mode not compatible with the errors bars.
So, one has to add the error bars with another floating bar chart.

In total:

hogi_2-1722876717046.png

 

100% GUI - 0% scripting.
here is the script:

View more...
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
Graph Builder(
	Size( 521, 429 ),
	Variables( X( :age ), Y( :height ) ),
	Elements(
		Points( X, Y, Legend( 2 ) ),
		Bar(
			X,
			Y,
			Bar Style( "Stacked" ),
			Summary Statistic( "Mean" ),
			Label( "Label by Value" )
		),
		Bar(
			X,
			Y,
			Bar Style( "Float" ),
			Summary Statistic( "Mean" ),
			Error Interval( "Standard Error" )
		)
	)
);


...  I hope this post will not be used to advocate against the new feature to specify the label position .

Tom_M1
Level I

Thanks for these posts. This will be helpful.

hogi
Level XII

Does a Heatmap Plot also have a "seg" to talk to?
not in this list:

hogi_0-1723060535118.png

is it called Heatmap Cells Seg

myseg << get description = "Heatmap Cells";

 

-> no.

hogi
Level XII

RectSeg.

Unfortunately, Heatmap Seg = Rect Seg is quite deaf : (