cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
UserID16644
Level V

Bivariate line style looping

Hi all

I am trying to create a bivariate plot with group that needs different line styles. However, the group is varying depending on the given data. Here's a sample data, where it is grouped according to their occupation. How can I create a loop inside my function to create line style?

                        biv = Bivariate( Y( :weight ), X( :height ),
										Group By(  :occupation ), << Fit Line );								
						rbiv = biv << report << Show Points( 1 );
						
						ymin = rbiv[Axis Box(1)] << Get Min;
						ymax = rbiv[Axis Box(1)] << Get Max;
						xmin = rbiv[Axis Box(2)] << Get Min;
						xmax = rbiv[Axis Box(2)] << Get Max;
													
						
						rbiv[Frame Box( 1 )] << {Frame Size( 205, 164 ), Marker Size( 2 ), Line Width Scale( 2 )};
						rbiv [Border Box (2)] << Sides(0);
												
						rbiv[Axis Box( 1 )]  << Format( "Best", 12 ) << Tick Font( style( 1 ), size( 9 ) )
											 << Show Major Grid( 1 ) << Show Minor Grid( 1 ) << Show Minor Ticks( 1 );
							
						rbiv[Axis Box( 2 )] << Format( "Best", 12 ) << Tick Font( style( 1 ), size( 9 ) )
											<< Show Major Grid( 1 ) << Show Minor Grid( 1 ) << Show Minor Ticks( 1 );
							
						rbiv[Text Edit Box( 1 )] << Set Font Size( 10 ) <<	Set Font Style( "Bold" );
						rbiv[Text Edit Box( 2 )] << Set Font Size( 10 ) <<	Set Font Style( "Bold" );
						rbiv[Outline Box( 2 )] << Close All Below;
						rbiv[Outline Box( 2 )] << Close All Like This;
1 ACCEPTED SOLUTION

Accepted Solutions
txnelson
Super User

Re: Bivariate line style looping

Here is another approach to the same issue

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
obj = dt << Bivariate( Y( :weight ), X( :height ) );
styleList = {"Solid", "Dashed", "Dotted", "DashDot", "DashDotDot"};

Summarize( dt, groups = by( :sex ) );
mystyle = styleList[2];
For( i = 1, i <= N Items( groups ), i++,
	Eval(
		Parse(
			"obj << Fit Where( :sex == \!"" || groups[i] || "\!", 
Fit Line( { Line Style( \!"" ||
			styleList[i] || "\!" )} ) )"
		)
	)
);
Jim

View solution in original post

8 REPLIES 8
jthi
Super User

Re: Bivariate line style looping

You could use associative array to save the settings (most likely best would be to use associative array inside associative array, but I got lazy), then use Fit Where with EvalEvalExpr. You need to know settings for each of the groups in this solution, but there are ways around this depending on your data/solution:

 

Names Default To Here(1);

dt = Current Data Table();

biv = Bivariate(Y(:weight), X(:height), Group By(:occupation));
rbiv = biv << report << Show Points(1);

aa_line = Associative Array();

aa_line["Dentist"] = {"Yellow", "Dotted"};
aa_line["Doctor"] = {"Green", "DashDotDot"};
aa_line["Engineer"] = {"Red", "Solid"};

For Each({{key_occ, value_list}}, aa_line,
	Eval(Eval Expr(biv << Fit Where(:occupation == Expr(key_occ), Fit Line({Line Color(Expr(value_list[1])), Line Style(Expr(value_list[2]))}))))
);

rbiv = biv << report << Show Points(1);

ymin = rbiv[Axis Box(1)] << Get Min;
ymax = rbiv[Axis Box(1)] << Get Max;
xmin = rbiv[Axis Box(2)] << Get Min;
xmax = rbiv[Axis Box(2)] << Get Max;

rbiv[Frame Box(1)] << {Frame Size(205, 164), Marker Size(2), Line Width Scale(2)};
rbiv[Border Box(2)] << Sides(0);
rbiv[Axis Box(1)] << Format("Best", 12) << Tick Font(style(1), size(9)) << Show Major Grid(1) << Show Minor Grid(1) << Show Minor Ticks(1);
rbiv[Axis Box(2)] << Format("Best", 12) << Tick Font(style(1), size(9)) << Show Major Grid(1) << Show Minor Grid(1) << Show Minor Ticks(1);
	
rbiv[Text Edit Box(1)] << Set Font Size(10) << Set Font Style("Bold");
rbiv[Text Edit Box(2)] << Set Font Size(10) << Set Font Style("Bold");
rbiv[Outline Box(2)] << Close All Below;
rbiv[Outline Box(2)] << Close All Like This;

 

 

-Jarmo
UserID16644
Level V

Re: Bivariate line style looping

Hi, I got an error. And also, I think this part should not be hard coded because like I said, the data is varying and changing from time to time

aa_line = Associative Array();

aa_line["Dentist"] = {"Yellow", "Dotted"};
aa_line["Doctor"] = {"Green", "DashDotDot"};
aa_line["Engineer"] = {"Red", "Solid"};

UserID16644_0-1647328175997.png

 

jthi
Super User

Re: Bivariate line style looping

I have to ask, how would you create a line style if you don't know how to style the lines as in you don't know how many styles you need?

 

That error is most likely caused by you using JMP version earlier than 16. The loop must be changed to regular For-loop instead of For Each (easy change).

-Jarmo
jthi
Super User

Re: Bivariate line style looping

After creating your Bivariate report, find references to Line Segs by either using XPath or Find Segs and then do something to those references:

 

Names Default To Here(1);

dt = Current Data Table();

biv = dt << Bivariate(Y(:weight), X(:height), Group By(:occupation), <<Fit Line);
rbiv = biv << report << Show Points(1);

rbiv[Outline Box(2)] << Close All Below;
rbiv[Outline Box(2)] << Close All Like This;

// get line seg references with XPath or Find Segs

// Xpath
//segs= rbiv2 << XPath("//IfSeg[contains(@description, 'Linear Fit occupation')]");

// Find Segs
frame = rbiv[FrameBox(1)];
segs = (frame << Find Segs(Line Seg()));

// Set the line properties by either looping over the references, or setting all at once by using segs as reference
// << Set Line Color, << Set Line Style, << Set Line Width
segs << Set Line Color("Green");
segs << Set Line Style("Dotted");
segs << Set Line Width(10);
-Jarmo
txnelson
Super User

Re: Bivariate line style looping

Here is another approach to the same issue

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
obj = dt << Bivariate( Y( :weight ), X( :height ) );
styleList = {"Solid", "Dashed", "Dotted", "DashDot", "DashDotDot"};

Summarize( dt, groups = by( :sex ) );
mystyle = styleList[2];
For( i = 1, i <= N Items( groups ), i++,
	Eval(
		Parse(
			"obj << Fit Where( :sex == \!"" || groups[i] || "\!", 
Fit Line( { Line Style( \!"" ||
			styleList[i] || "\!" )} ) )"
		)
	)
);
Jim
UserID16644
Level V

Re: Bivariate line style looping

Hi txnelson,
The line legends works fine but when I tried putting this loop into my function that needs to generate multiple plots, it only generates one plot when it should be four (4 y columns).
Please help in looping the function 
Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class Families.jmp" );

bivplot_line1 = Function({ ycol, xcol }, {plot},
				
	biv = Bivariate( Y( Column( dt, ycol ) ), X( Column( dt, xcol )) );													
	rbiv = biv << report << Show Points( 1 );					
	styleList = {"Solid", "Dashed", "Dotted", "DashDot", "DashDotDot"};
	Summarize( dt, groups = by ( :Sex ) );
	mystyle = styleList[2];
		For( i = 1, i <= N Items( groups ), i++,
			Eval(
			  Parse( "biv << Fit Where( :Sex == \!"" || groups[i] || "\!", 
				Fit Line( { Line Style( \!"" || styleList[i] || "\!" )} ) )"
			  )
			)
		);
     );
					
colname = {"weight"};
colnamex = {"age", "height", "siblings ages", "age vector"};

For(i = 1, i <= Nitems(colnamex), i++,
		bivplot_line1( colname[1],colnamex[i]) );	
		
 
txnelson
Super User

Re: Bivariate line style looping

There are 2 issues.  You are using the index variable "i" in 2 different loops.  The second loop is changing the values of "i", which increases its value when the first loop starts the second loop.  It finds that "i" is greater than nitems(colnamex), and therefore it stops the loop. If you change "i" to "k" for

 

For(k = 1, k <= Nitems(colnamex), k++,
		bivplot_line1( colname[1],colnamex[ik) );

the code will loop.

The second issue is that you have 2 columns specified, sibling ages and age vector, which are not valid columns to be used in the bivariate.  Therefore, in your example, the code will only correctly run for 2 columns.

Jim
UserID16644
Level V

Re: Bivariate line style looping

Totally missed that! Thank you, I understood it completely