How to uniformly set the label position above or below the data point
Basic Data Analysis and Modeling
Re: 如何统一设置标签位置在数据点上方或下方Dummy graph to play with:

Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
Data Table( "Big Class" ) << Select All Rows << Label;
:weight << Label( 1 );
:name << Label( 0 );
Graph Builder(
Size( 437, 428 ),
Summary Statistic( "Median" ),
Graph Spacing( 4 ),
Variables( X( :name ), Y( :weight ) ),
Elements( Points( X, Y, Legend( 4 ) ) ),
Local Data Filter(
Add Filter(
columns( :name ),
Where( :name == {"AMY", "BARBARA", "CAROL", "CHRIS", "CLAY", "DANNY"} ),
Display( :name, N Items( 15 ), Find( Set Text( "" ) ) )
)
)
);
Re: 如何统一设置标签位置在数据点上方或下方One approach is via JSL - just add the offsets "manually" for all the labels - via a list:

// create a list of identical offsets
labels = As list(Index(0,10))[1]; // surprise: the fist index is 0!
offset Expr = Expr(Label Offset());
offsets= For Each ({label}, labels, Insert Into(offset Expr,Eval List({label,0.,-20}))); // vertical offset: -20
// send the command to the Point plot
mySeg = current report()[FrameBox(1)] << find seg(MarkerSeg);
Eval (Eval Expr(mySeg << Expr(Name expr(offset Expr) )))
Re: 如何统一设置标签位置在数据点上方或下方I'm not sure if you can easily adjust label offsets without scripting.
Below is very quick example how it might be possible to do it with JSL
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
gb = dt << Graph Builder(
Size(525, 512),
Show Control Panel(0),
Variables(X(:age), Y(:height)),
Elements(
Points(X, Y, Legend(3), Summary Statistic("Mean"), Label("Label by Value"))
)
);
frame = Report(gb)[FrameBox(1)];
seg = (frame << FindSeg(Marker Seg(1)));
For(i = 0, i <= N Items(seg << get markers), i++,
Eval(EvalExpr(
seg << Label Offset(Expr(Eval List({i, -5, -5})));
));
);
Re: 如何统一设置标签位置在数据点上方或下方Solved, thanks!

dt3 = Data Table("光伏供应链价格汇总");
obj1 = dt3 << Graph Builder(
Size(1476, 745),
Show Control Panel(0),
Legend Position("Inside Right"),
Fit to Window("Off"),
Variables(X(:日期), Y(:单价), Group X(:产品), Group Y(:型号)),
Elements(
Points(X, Y, Legend(5), Label("Label by Value"), Label Format("Fixed Dec", 7, 2)),
Smoother(X, Y, Legend(6))
),
SendToReport(
Dispatch({}, "日期", ScaleBox,
{Min(min_date - 86400), Max(max_date + 86400), Interval("Day"), Inc(1),
Minor Ticks(0), Label Row(
{Label Orientation("Vertical"), Show Major Grid(0), Show Minor Grid(0)}
)}
),
Dispatch({}, "单价", ScaleBox,
{Min(0.2), Max(2.5), Inc(0.5), Minor Ticks(1),
Label Row({Show Major Grid(0), Show Minor Grid(0)})}
)
)
);
Wait(1);
excluded_rows = dt3 << Get Excluded Rows; //获取排除行矩阵
mm = N Row(excluded_rows); //获取排除行数
nn = (N Row(dt3) - mm) / 7;
report = obj1 << Report;
indices = {4, 5, 8, 9, 10, 20, 21};
For(idx = 1, idx <= N Items(indices), idx++,
i = indices[idx];
frame = report[FrameBox(i)];
For(j = 0, j <= nn, j++,
seg = frame << Find Seg(Marker Seg(1));
seg << Label Offset({j, -10, -10});
);
);
Edit (jthi): Added JSL formatting
Re: 如何统一设置标签位置在数据点上方或下方As an alternative, you can use a more automated approach (e.g. if you don't want to type in he framebox indices manually or you use Overlay and there are more Segs):
- find al lframeboxes
- for each framebox, find all segs
- for each seg, find all markers
- apply the offset
Names Default to Here(1);
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
Data Table( "Big Class" ) << Select All Rows << Label;
:weight << Label( 1 );
:name << Label( 0 );
gb = dt << Graph Builder(
Size( 437, 413 ),
Summary Statistic( "Median" ),
Graph Spacing( 4 ),
Variables( X( :height ), Y( :weight ), Wrap( :age ), Overlay( :sex ) ),
Elements( Points( X, Y ), Smoother( X, Y, Legend( 2 ) ) )
);
fbs = Current Report() << xpath( "//FrameBox" );
For Each( {frame}, fbs,
segs = (frame << FindSegs);
For Each( {seg}, segs,
Try( // skip non-Marker-segs
markers = seg << get markers;
For Each( {x, i}, markers,
seg << Label Offset( {i-1, -10, -10} )
);
);
);
);Re: 如何统一设置标签位置在数据点上方或下方Note to myself:
Cool, no expression handling is needed to get the correct "i-1" in
seg << Label Offset( {i-1, -10, -10} )
The seg receives the message - sees "i" and looks it up: Eval(i) -Similar to the column name in new column(column name)
On the other hand, expression handling is needed for
Eval (Eval Expr(mySeg << Expr(Name expr(offset Expr) )))
With
mySeg << offset Expr
one gets the error message:

The Seg just checks the list of accepted messages and offset Expr is not listed.
Name Expr(offset Expr) is not checked
- and Eval(offset Expr) (like for i inside the message) wouldn't make sense.