cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Register for our Discovery Summit 2024 conference, Oct. 21-24, where you’ll learn, connect, and be inspired.
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 XI

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?
Graphbuilder: option to rotate 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 XI

cool! amazing!
thanks.

hogi
Level XI

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 XI

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.

I added this idea as a subtopic to this wish:
https://community.jmp.com/t5/JMP-Wish-List/Graphbuilder-option-to-rotate-labels/idc-p/778238/highlig...