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
RMSEBird223
Level II

How do I change point data point labels of graph builder in an automated way?

Hi all,

I need to change the data point label positions. My problem is that I need to define the new label positions (see variable LabelPosText) inside the expression statement. I know this wouldn't be necessary in the example below, but I want to spare you the effort of working through my long code, so I'm showing you a simplified example.

I am now failing to get the content of the variable LabelPosText into the Graph Builder expression part (the respective line is labeled with //here I need help ). I have tried several combinations of Eval(), Eval Expr(), etc., but nothing has worked for me.

Thanks a lot for your help!

 

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );

Eval( 
	Parse(
		"dt  << New Script(\!"test script\!",
		    
//defining new label positions for some data points Rows = dt << get rows where( :Sex == \!"F\!" ); LabelPosText = \!"\!"; For Each({row, idx}, Rows, WeightValue = Column( dt, \!"weight\!")[row]; HeightValue = Column( dt, \!"height\!")[row]; LabelPosText = LabelPosText || \!"{\!"|| char(row-1) ||\!", -5, 12, \!"|| char(WeightValue) ||\!", \!"|| char(HeightValue) ||\!"}\!"; if(idx < N Items(Rows), LabelPosText = LabelPosText || \!", \!" ) ); Graph Builder( Size( 528, 456 ), Show Control Panel( 0 ), Variables( X( :weight ), Y( :height ) ), Elements( Points( X, Y, Legend( 5 ) ) ), SendToReport( Dispatch( {}, \!"Graph Builder\!", FrameBox, {DispatchSeg( Marker Seg( 1 ), {Label Offset( LabelPosText ), //here I need help ;) Set Force Labels( \!"Label by Row\!" )} )} ) ) ) )" )

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
jthi
Super User

Re: How do I change point data point labels of graph builder in an automated way?

It is possible to calculate them inside. If there is a possibility that they change between different table script runs, they should be inside it otherwise I would move them outside and evaluate the value inside the script.

 

Generally, I would always avoid using EvilParse (Eval(Parse()) as it is a nightmare to debug and, in my opinion, there is almost never a reason to use it. This does look complicated, but I would approach this with something like this

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Big Class.jmp");

// Label Offset has very annoying format to build as it isn't list with lists
// but just something with lists
table_script = Expr(
	Names Default To Here(1);
	
	Rows = Current Data Table() << get rows where(:Sex == "F");
	offsets = Expr(Label Offset());
	
	For Each({row, idx}, Rows,
		WeightValue = :weight[row];
		HeightValue = :height[row];
		l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
		Insert Into(offsets, l);
	);
	
	Eval(Substitute(
		Expr(Graph Builder(
			Size(528, 456),
			Show Control Panel(0),
			Variables(X(:weight), Y(:height)),
			Elements(Points(X, Y, Legend(5))),
			SendToReport(
				Dispatch({}, "Graph Builder", FrameBox,
					{DispatchSeg(
						Marker Seg(1),
						{_labeloffset_,
						Set Force Labels("Label by Row")}
					)}
				)
			)
		)),
		Expr(_labeloffset_), Name Expr(offsets)
	));	
);

Eval(EvalExpr(
	dt << New Script("test script", 
		Expr(Name Expr(table_script));
	);	
));

You could also move the Label Offset outside of graph builder and send the message to the graph builder after it has been built (I'm not sure if this sets Set Force Labels correctly)

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Big Class.jmp");

// Label Offset has very annoying format to build as it isn't list with lists
// but just something with lists
table_script = Expr(
	Names Default To Here(1);
	
	Rows = Current Data Table() << get rows where(:Sex == "F");
	offsets = Expr(Label Offset());
	
	For Each({row, idx}, Rows,
		WeightValue = :weight[row];
		HeightValue = :height[row];
		l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
		Insert Into(offsets, l);
	);
	
	gb = Graph Builder(
		Size(528, 456),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height)),
		Elements(Points(X, Y, Legend(5))),
		SendToReport(
			Dispatch({}, "Graph Builder", FrameBox,
				{DispatchSeg(
					Marker Seg(1),
					{Set Force Labels("Label by Row")}
				)}
			)
		)
	);
	
	ms = Report(gb)[FrameBox(1)] << Find Seg(MarkerSeg(1));
	Eval(EvalExpr(Send(ms, Expr(Name Expr(offsets)))));
	wait(0);
);

Eval(EvalExpr(
	dt << New Script("test script", 
		Expr(Name Expr(table_script));
	);	
));

The final table script should look like this

Names Default To Here(1);
Rows = Current Data Table() << get rows where(:Sex == "F");
offsets = Expr(Label Offset());
For Each({row, idx}, Rows,
	WeightValue = :weight[row];
	HeightValue = :height[row];
	l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
	Insert Into(offsets, l);
);
gb = Graph Builder(
	Size(528, 456),
	Show Control Panel(0),
	Variables(X(:weight), Y(:height)),
	Elements(Points(X, Y, Legend(5))),
	SendToReport(
		Dispatch({}, "Graph Builder", FrameBox,
			{DispatchSeg(Marker Seg(1), {Set Force Labels("Label by Row")})}
		)
	)
);
ms = Report(gb)[FrameBox(1)] << Find Seg(Marker Seg(1));
Eval(Eval Expr(ms << Expr(Name Expr(offsets))));
Wait(0);

and the script you get from graph builder

Graph Builder(
	Size(528, 456),
	Show Control Panel(0),
	Variables(X(:weight), Y(:height)),
	Elements(Points(X, Y, Legend(5))),
	SendToReport(
		Dispatch({}, "Graph Builder", FrameBox,
			{DispatchSeg(
				Marker Seg(1),
				{Label Offset(
					{8, -5, 12, 112, 60},
					{0, -5, 12, 95, 59},
					{9, -5, 12, 107, 61},
					{1, -5, 12, 123, 61},
					{10, -5, 12, 67, 56},
					{2, -5, 12, 74, 55},
					{3, -5, 12, 145, 66},
					{4, -5, 12, 64, 52},
					{15, -5, 12, 81, 61},
					{16, -5, 12, 91, 62},
					{17, -5, 12, 142, 65},
					{18, -5, 12, 84, 63},
					{19, -5, 12, 85, 62},
					{27, -5, 12, 92, 62},
					{28, -5, 12, 112, 64},
					{34, -5, 12, 112, 65},
					{35, -5, 12, 115, 60},
					{37, -5, 12, 116, 62}
				), Set Force Labels("Label by Row")}
			)}
		)
	)
);
-Jarmo

View solution in original post

4 REPLIES 4
jthi
Super User

Re: How do I change point data point labels of graph builder in an automated way?

What are you trying to do? Is the calculation for LabelPosText supposed to be inside the table script or just the graph?

-Jarmo
RMSEBird223
Level II

Re: How do I change point data point labels of graph builder in an automated way?

Hi, yes, the LabelPosText is supposed to be inside the table script. Is this generally possible? Or should I think of a way to take it out?

 

 

jthi
Super User

Re: How do I change point data point labels of graph builder in an automated way?

It is possible to calculate them inside. If there is a possibility that they change between different table script runs, they should be inside it otherwise I would move them outside and evaluate the value inside the script.

 

Generally, I would always avoid using EvilParse (Eval(Parse()) as it is a nightmare to debug and, in my opinion, there is almost never a reason to use it. This does look complicated, but I would approach this with something like this

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Big Class.jmp");

// Label Offset has very annoying format to build as it isn't list with lists
// but just something with lists
table_script = Expr(
	Names Default To Here(1);
	
	Rows = Current Data Table() << get rows where(:Sex == "F");
	offsets = Expr(Label Offset());
	
	For Each({row, idx}, Rows,
		WeightValue = :weight[row];
		HeightValue = :height[row];
		l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
		Insert Into(offsets, l);
	);
	
	Eval(Substitute(
		Expr(Graph Builder(
			Size(528, 456),
			Show Control Panel(0),
			Variables(X(:weight), Y(:height)),
			Elements(Points(X, Y, Legend(5))),
			SendToReport(
				Dispatch({}, "Graph Builder", FrameBox,
					{DispatchSeg(
						Marker Seg(1),
						{_labeloffset_,
						Set Force Labels("Label by Row")}
					)}
				)
			)
		)),
		Expr(_labeloffset_), Name Expr(offsets)
	));	
);

Eval(EvalExpr(
	dt << New Script("test script", 
		Expr(Name Expr(table_script));
	);	
));

You could also move the Label Offset outside of graph builder and send the message to the graph builder after it has been built (I'm not sure if this sets Set Force Labels correctly)

Names Default To Here(1);

dt = Open("$SAMPLE_DATA/Big Class.jmp");

// Label Offset has very annoying format to build as it isn't list with lists
// but just something with lists
table_script = Expr(
	Names Default To Here(1);
	
	Rows = Current Data Table() << get rows where(:Sex == "F");
	offsets = Expr(Label Offset());
	
	For Each({row, idx}, Rows,
		WeightValue = :weight[row];
		HeightValue = :height[row];
		l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
		Insert Into(offsets, l);
	);
	
	gb = Graph Builder(
		Size(528, 456),
		Show Control Panel(0),
		Variables(X(:weight), Y(:height)),
		Elements(Points(X, Y, Legend(5))),
		SendToReport(
			Dispatch({}, "Graph Builder", FrameBox,
				{DispatchSeg(
					Marker Seg(1),
					{Set Force Labels("Label by Row")}
				)}
			)
		)
	);
	
	ms = Report(gb)[FrameBox(1)] << Find Seg(MarkerSeg(1));
	Eval(EvalExpr(Send(ms, Expr(Name Expr(offsets)))));
	wait(0);
);

Eval(EvalExpr(
	dt << New Script("test script", 
		Expr(Name Expr(table_script));
	);	
));

The final table script should look like this

Names Default To Here(1);
Rows = Current Data Table() << get rows where(:Sex == "F");
offsets = Expr(Label Offset());
For Each({row, idx}, Rows,
	WeightValue = :weight[row];
	HeightValue = :height[row];
	l = Eval List({row - 1, -5, 12, WeightValue, HeightValue});
	Insert Into(offsets, l);
);
gb = Graph Builder(
	Size(528, 456),
	Show Control Panel(0),
	Variables(X(:weight), Y(:height)),
	Elements(Points(X, Y, Legend(5))),
	SendToReport(
		Dispatch({}, "Graph Builder", FrameBox,
			{DispatchSeg(Marker Seg(1), {Set Force Labels("Label by Row")})}
		)
	)
);
ms = Report(gb)[FrameBox(1)] << Find Seg(Marker Seg(1));
Eval(Eval Expr(ms << Expr(Name Expr(offsets))));
Wait(0);

and the script you get from graph builder

Graph Builder(
	Size(528, 456),
	Show Control Panel(0),
	Variables(X(:weight), Y(:height)),
	Elements(Points(X, Y, Legend(5))),
	SendToReport(
		Dispatch({}, "Graph Builder", FrameBox,
			{DispatchSeg(
				Marker Seg(1),
				{Label Offset(
					{8, -5, 12, 112, 60},
					{0, -5, 12, 95, 59},
					{9, -5, 12, 107, 61},
					{1, -5, 12, 123, 61},
					{10, -5, 12, 67, 56},
					{2, -5, 12, 74, 55},
					{3, -5, 12, 145, 66},
					{4, -5, 12, 64, 52},
					{15, -5, 12, 81, 61},
					{16, -5, 12, 91, 62},
					{17, -5, 12, 142, 65},
					{18, -5, 12, 84, 63},
					{19, -5, 12, 85, 62},
					{27, -5, 12, 92, 62},
					{28, -5, 12, 112, 64},
					{34, -5, 12, 112, 65},
					{35, -5, 12, 115, 60},
					{37, -5, 12, 116, 62}
				), Set Force Labels("Label by Row")}
			)}
		)
	)
);
-Jarmo
hogi
Level XII

Re: How do I change point data point labels of graph builder in an automated way?

hogi_2-1732868456364.png
very new, thanks for this info - especially with No Labels it can be really useful!!

 


For Label Offset, I couldn't find a lot of documentation  - seems to be no functionality which is intended to be used by users?

Interesting:
- the x /y coordinates just seem to be used for double checking. This can be used to simplify the command:
just provide wrong values for MALE to get rid of them.

- What coordinate system is used for the offsets? a constant offset doesn't result in a constant shift for each label.

hogi_1-1732868336741.png

 

 

dt = Open( "$SAMPLE_DATA/Big Class.jmp" );

LabelPosOffsets = Expr(Label Offset());
For Each row(
	Insert Into(LabelPosOffsets,Eval List({row() - 1, -100,100,:weight+if( sex=="F", 0,1),:height}))
);

Eval (Eval Expr(Graph Builder(
	Size( 528, 456 ),
	Show Control Panel( 0 ),
	Variables( X( :weight ), Y( :height ), Color( :sex ) ),
	Elements( Points( X, Y, Legend( 5 ) ) ),
	SendToReport(
		Dispatch( {}, "Graph Builder", FrameBox,
			{DispatchSeg(
				Marker Seg( 1 ),
				{ Expr(Name Expr(LabelPosOffsets) ), Set Force Labels( "Label by Row" )}
			)}
		)
	)
)));