cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Choose Language Hide Translation Bar
SDF1
Super User

Help Scripting an Interactive window that updates upon user choices

Dear All,

 

  I am writing a script that will be deployed to users in my organization to perform some simple quick statistics for the user without having to invoke the Distribution platform. The script is below with a screenshot of what I currently have, then a list of the things I'm having trouble with. The users will be running JMP 16.1, I am running JMP Pro 16.0. All machines are windows 10, 64-bit machines.

 

  The intended purpose of the script is to show the numerical columns (maybe later I will deal with categorical columns) and depending on which radio button is selected, it will perform some simple statistics and display the results in the same window with a column labeled Stats for the type of statistic calculated and Values for the results of said calculations. The Results panel box should update upon the selection of the radio button after they have selected the appropriate column in the Select Column panel box.

 

Current JMP script (FYI, I'm testing it out on the familiar Big Class.jmp file):

Names Default To Here( 1 );
//Clear Symbols();
//the width of the column list box in pixels
lbWidth = 100;

dt = Current Data Table();

//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};
StatsListC = {};

//Expression to do math
MathA = Expr(
	response_col = Column( dt, Eval( Eval Expr( Expr( ycols ) ) ) );
	ymean = Col Mean( response_col );
	ystdev = Col Std Dev( response_col );
	ymin = Col Min( response_col );
	ymax = Col Max( response_col );
	yrange = ymax - ymin;
	yN = Col Number( response_col );
	NumResultsA = {ymean, ystdev, ymin, ymax, yrange, yN};
);

//Expresseion for other math
MathB = Expr(
	
);

ValueDlg = Expr(
	nwin = New Window( "GUI for quick stats",
		<<Return Result,
		<<On Validate,
		Border Box( Left( 3 ), Top( 2 ),
			V List Box(
				Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ),
				H List Box(
					V List Box(
						Panel Box( "Select Columns", ColListData = Col List Box( dt, All, Grouped, width( lbWidth ), nLines( 10 ) ) ),
						Panel Box( "Choose quick stats",
							V List Box(
								qstats = Radio Box(
									{StatsListA, StatsListB, StatsListC},
									<<Set Function(
										Function( {this, index},
											{lb},
											lb = this << sib;
											((lb << child) << sib) << Set Text( Char( index ) );
											((((lb << child) << sib) << sib) << sib) << Set Text( Char( this << get selected ) );
										)
									)
								)
							)
						), 

					),
					Panel Box( "Results", Lineup Box( N Col( 1 ), H List Box( String Col Box( "Stats", {} ), Number Col Box( "Values", {} ) ) ) ),
					Panel Box( "Action",
						Lineup Box( N Col( 1 ),
							Button Box( "Cancel/End", nwin << Close Window ),
							Text Box( " " ),
							Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) )
						)
					), 

				), 

			), 

		), 

	);

);

ValueDlg;

 

This is what I have so far:

DiedrichSchmidt_0-1632406235583.png

 

Here is the list of things I'm having trouble with:

  1. The call for the Radio Box() lists the local variable name "StatsListA", etc. instead of actually listing out the stats that will be calculated. For example, the first radio button should have the following list behind it: Mean, Std Dev, Max, Min, Range, N. This should also be for the StatsListB and StatsListC (I haven't defined the C list yet). I'm not sure how to get it to evaluate the pre-defined list I make at the top of the JSL code. I'd prefer not to have to write out each and every item as I might want to change the items in the list and it's easier to change the local variable StatsListX instead of editing the Radio Box() call each time.
  2. Right now, I'd prefer to not list ALL columns, but just numeric. When I change the option in Col List Box() from All to Numeric (with or without ""), I get an empty list of columns. Can't figure out why this is happening, when it should list only the Numeric columns when I have that option defined.
  3. This is the hardest one I think: As mentioned before, I'd like the results in the Panel box "Results" to be updated with a column on the left "Stats" (which lists the statistics from StatsListX and the calculation results for those stats in the right column "Values". This should be updated with each click of a radio button. So if you were originally looking at :height, but wanted to look at :weight, you'd select :weight and then click on one of the radio buttons to get the relevant statistical summary. I tried following the Set Function example shown here, but have been unsuccessful (I do not know the Set Function call very well).DiedrichSchmidt_1-1632406884261.png

 

  The Expr() for the MathA was intended to be called by closing the original window and opening a new one with the results, but after doing some more research in the JMP Discussions, I found that one can update fields within an existing window, which is how I prefer to approach this problem. So, I know that original coding at the top of my code is not the right code for what I intend to do.

 

  Any help on this is much appreciated.

 

Thanks!,

DS

4 ACCEPTED SOLUTIONS

Accepted Solutions
jthi
Super User

Re: Help Scripting an Interactive window that updates upon user choices

I did some quick testing and attached the script. It has possible ideas how you approach this, but might not be the best solutions.

1. Handled with Associative Arrays and Expressions.

 

2. Had to use some weird syntax for this ColListData = Col List Box(dt, All, <<Set Data Type("numeric"), Grouped, width(lbWidth), nLines(10))

3. Set Function is handling this with Evals.

 

The attached script will give the best idea how I approached this for now.

jthi_0-1632409725184.png

 

 

-Jarmo

View solution in original post

ian_jmp
Staff

Re: Help Scripting an Interactive window that updates upon user choices

Regarding point 1., and adding just a little to the reply from @jthi, you can do:

Names Default To Here( 1 );

//the width of the column list box in pixels
lbWidth = 100;

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

//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};

//RadioBox() argument
rbArg = EvalList({ConcatItems(StatsListA, ", "), ConcatItems(StatsListB, ", ")});

//Window
New Window( "GUI for quick stats",
		Panel Box( "Select Columns", ColListData = Col List Box( dt, all, <<Set Data Type("numeric"), Grouped, width( lbWidth ), nLines( 10 ) ) ),
		Panel Box( "Choose quick stats", qstats = Radio Box(rbArg))
		);

 

View solution in original post

jthi
Super User

Re: Help Scripting an Interactive window that updates upon user choices

1. Because of using Associative Array the statistics will be re-ordered. You could maybe just use lists and modify referencing to use indexes

2. Modifying how you calculate 0 values could work. You could for example use example Loc() with N Items():

statZero = Expr(N Items(Loc(tempCol << get as matrix, 0)));

jthi_0-1632423107819.png

 

 

-Jarmo

View solution in original post

SDF1
Super User

Re: Help Scripting an Interactive window that updates upon user choices

Hi @jthi and @ian_jmp ,

 

  Thank you both for your great help! Thanks for the last two final hints @jthi , I was able to overcome the associative array alphabetical "issue". I do like the power of the AAs, I can see where they can come in handy, but I need a certain order to be maintained because of the users.

 

  I was able to make the changes with the lists suggestion and your suggestion for the Count Zero problem I had. Thanks! The code is working as expected, now I'll need to expand it for doing categorical columns and then survey my users to see what actual list of statistics they need.

 

  Thanks again for all your help! The working code (at least for numerical columns) is below.

 

Thanks!,

DS

Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;

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

//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};

//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
	Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
	Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
	Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
	Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
	Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
	Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
	Col N Missing( tempCol )
);
statZero = Expr(
	N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );

//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );

//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
	Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
	Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
	Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
	Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);


//User window
ValueDlg = Expr(
	nwin = New Window( "GUI for quick stats",
		<<Return Result,
		<<On Validate,
		Border Box( Left( 3 ), Top( 2 ),
			V List Box(
				Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ),
				H List Box(
					V List Box(
						Panel Box( "Select Columns",
							ColListData = Col List Box( dt, All, <<Set Data Type( "Numeric" ), Grouped, width( lbWidth ), nLines( 10 ) )
						),
						Panel Box( "Choose quick stats",
							qstats = Radio Box(
								rbArg,
								<<Set Function(
									Function( {this, index},
										{},
										scb << Set( {} );
										ncb << Set( {} );
										vals = this << get;
										tempCol = Column( dt, (ColListData << Get Selected) );
										scb << Set( StatList[vals] );
										ncb << Set( StatListRes(vals)[vals] );
									)
								)
							)
						)
					),
					Panel Box( "Results",
						Lineup Box( N Col( 1 ), H List Box( scb = String Col Box( "Stats", {} ), ncb = Number Col Box( "Values", {} ) ) )
					),
					Panel Box( "Action",
						Lineup Box( N Col( 1 ),
							Button Box( "Cancel/End", nwin << Close Window ),
							Text Box( " " ),
							Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) )
						)
					), 

				), 

			), 

		), 

	);

);

ValueDlg;

View solution in original post

11 REPLIES 11
jthi
Super User

Re: Help Scripting an Interactive window that updates upon user choices

I did some quick testing and attached the script. It has possible ideas how you approach this, but might not be the best solutions.

1. Handled with Associative Arrays and Expressions.

 

2. Had to use some weird syntax for this ColListData = Col List Box(dt, All, <<Set Data Type("numeric"), Grouped, width(lbWidth), nLines(10))

3. Set Function is handling this with Evals.

 

The attached script will give the best idea how I approached this for now.

jthi_0-1632409725184.png

 

 

-Jarmo
jimloughlin
Level III

Re: Help Scripting an Interactive window that updates upon user choices

When I run statsstart.jcl, I get the following error:

 

Name Unresolved: tempCol{1} in access or evaluation of 'tempCol' , tempCol/*###*/

 

Perhaps because I am running v13.2.1?

Jim Loughlin
Loughlin Consulting
SDF1
Super User

Re: Help Scripting an Interactive window that updates upon user choices

Hi @jimloughlin ,

 

  I think that was just some debugging code that @jthi was using when providing his suggested edits to my original code I posted. I'm posting an updated one that takes into accounts some suggested edits from other people who wrote on this thread. I'll tag you when I post the updated script. I have it working just fine with the Big Class.jmp data table.

 

Thanks!,

DS

ian_jmp
Staff

Re: Help Scripting an Interactive window that updates upon user choices

Regarding point 1., and adding just a little to the reply from @jthi, you can do:

Names Default To Here( 1 );

//the width of the column list box in pixels
lbWidth = 100;

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

//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"95% quantile", "50% quantile", "5% quantile"};

//RadioBox() argument
rbArg = EvalList({ConcatItems(StatsListA, ", "), ConcatItems(StatsListB, ", ")});

//Window
New Window( "GUI for quick stats",
		Panel Box( "Select Columns", ColListData = Col List Box( dt, all, <<Set Data Type("numeric"), Grouped, width( lbWidth ), nLines( 10 ) ) ),
		Panel Box( "Choose quick stats", qstats = Radio Box(rbArg))
		);

 

SDF1
Super User

Re: Help Scripting an Interactive window that updates upon user choices

Hi @jthi and @ian_jmp ,

 

  Thank you two so much for the fast feedback! Your suggestions worked great and I was able to make much more progress. Now I'm having issues with just two probably very simple things, I'm including the updated code below. Just as an FYI, I deleted some values in :height and added some zeroes in :height to test it

 

Issues:

  1. When it lists the statistics, it does them by alphabetical order, I'd like to maintain the order I have defined in my lists, is this possible?
  2. I'm trying to calculate the proportion zero and non-zero by first counting the number of zeroes. Unfortunately, it's not working quite right. I can put the summarize within an Expr(), but then I'm not able to define the associative array, and I don't get the right subsequent calculations. I'm sure there is an easier way to do this, but I couldn't find any direct command in JSL to count only zeros. I've entered 5 missing values, and 7 zero values manually. So, the prop-non-zero should be 0.8 and the prop-zero should be 0.2. 
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;

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

//List of statistics to calculate
StatsListA = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsListB = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsListC = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};

//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsListA, ", " ), Concat Items( StatsListB, ", " ), Concat Items( StatsListC, ", " )} );

//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
	Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
	Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
	Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
	Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
	Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
	Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
	Col N Missing( tempCol )
);

//Here's where I'm having trouble with the N Zero and proportions zero and non-zero. Expr( Summarize( dt, eg = By( tempCol ), em = Count( tempCol ) ) ); PropTemp1 = Expr( Associative Array( eg, em ) ); statZero = Expr( PropTemp1["0"] ); statProp0 = Expr( statZero / statN ); statPropn0 = Expr( 1 - statProp0 ); maths = Associative Array(); maths["StatListA"] = Associative Array( StatsListA, {statMean, statStd, statMax, statMin, statRange, statN} ); maths["StatListB"] = Associative Array( StatsListB, {., statQ95, statQ75, statQ50, statQ25, statQ5} ); maths["StatListC"] = Associative Array( StatsListC, {statN, statMiss, statZero, statProp0, statPropn0} ); rbOptions = maths << Get Keys; //User window ValueDlg = Expr( nwin = New Window( "GUI for quick stats", <<Return Result, <<On Validate, Border Box( Left( 3 ), Top( 2 ), V List Box( Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ), H List Box( V List Box( Panel Box( "Select Columns", ColListData = Col List Box( dt, All, <<Set Data Type( "Numeric" ), Grouped, width( lbWidth ), nLines( 10 ) ) ), Panel Box( "Choose quick stats", qstats = Radio Box( rbArg, <<Set Function( Function( {this, index}, {}, scb << Set( {} ); ncb << Set( {} ); vals = this << get; tempAa = maths[rbOptions[vals]]; tempCol = Column( dt, (ColListData << Get Selected) ); scb << Set( tempAa << get keys ); ncb << Set( Eval List( tempAa << get values ) ); ) ) ) ) ), Panel Box( "Results", Lineup Box( N Col( 1 ), H List Box( scb = String Col Box( "Stats", {} ), ncb = Number Col Box( "Values", {} ) ) ) ), Panel Box( "Action", Lineup Box( N Col( 1 ), Button Box( "Cancel/End", nwin << Close Window ), Text Box( " " ), Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) ) ) ), ), ), ), ); ); ValueDlg;

DiedrichSchmidt_0-1632422074034.png

 

  Thanks again for your help so far, and I hope you can help with these other small things.

 

Thanks!,

DS

 

jthi
Super User

Re: Help Scripting an Interactive window that updates upon user choices

1. Because of using Associative Array the statistics will be re-ordered. You could maybe just use lists and modify referencing to use indexes

2. Modifying how you calculate 0 values could work. You could for example use example Loc() with N Items():

statZero = Expr(N Items(Loc(tempCol << get as matrix, 0)));

jthi_0-1632423107819.png

 

 

-Jarmo
SDF1
Super User

Re: Help Scripting an Interactive window that updates upon user choices

Hi @jthi and @ian_jmp ,

 

  Thank you both for your great help! Thanks for the last two final hints @jthi , I was able to overcome the associative array alphabetical "issue". I do like the power of the AAs, I can see where they can come in handy, but I need a certain order to be maintained because of the users.

 

  I was able to make the changes with the lists suggestion and your suggestion for the Count Zero problem I had. Thanks! The code is working as expected, now I'll need to expand it for doing categorical columns and then survey my users to see what actual list of statistics they need.

 

  Thanks again for all your help! The working code (at least for numerical columns) is below.

 

Thanks!,

DS

Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 205;

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

//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};

//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
	Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
	Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
	Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
	Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
	Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
	Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
	Col N Missing( tempCol )
);
statZero = Expr(
	N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );

//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );

//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
	Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
	Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
	Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
	Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);


//User window
ValueDlg = Expr(
	nwin = New Window( "GUI for quick stats",
		<<Return Result,
		<<On Validate,
		Border Box( Left( 3 ), Top( 2 ),
			V List Box(
				Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ),
				H List Box(
					V List Box(
						Panel Box( "Select Columns",
							ColListData = Col List Box( dt, All, <<Set Data Type( "Numeric" ), Grouped, width( lbWidth ), nLines( 10 ) )
						),
						Panel Box( "Choose quick stats",
							qstats = Radio Box(
								rbArg,
								<<Set Function(
									Function( {this, index},
										{},
										scb << Set( {} );
										ncb << Set( {} );
										vals = this << get;
										tempCol = Column( dt, (ColListData << Get Selected) );
										scb << Set( StatList[vals] );
										ncb << Set( StatListRes(vals)[vals] );
									)
								)
							)
						)
					),
					Panel Box( "Results",
						Lineup Box( N Col( 1 ), H List Box( scb = String Col Box( "Stats", {} ), ncb = Number Col Box( "Values", {} ) ) )
					),
					Panel Box( "Action",
						Lineup Box( N Col( 1 ),
							Button Box( "Cancel/End", nwin << Close Window ),
							Text Box( " " ),
							Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) )
						)
					), 

				), 

			), 

		), 

	);

);

ValueDlg;
jthi
Super User

Re: Help Scripting an Interactive window that updates upon user choices

After you get the script working mostly as you want, there are couple of visual things I would consider:

  1. The table size changes and makes the window "bounce" a bit
  2. If user has no column selected there will be an error
  3. If no datatables are open you could stop script execution and inform user
  4. If user changes the column in Col List Box, you should maybe either recalculate stats with the current selection of Radio Box OR set the table empty.

Couple of ideas:

  • For Results panel box. You can use Set Widths to prevent the table changing horizontal size and hidden placeholder String Col Box with pre-defined list size to prevent vertical size changes
  • Select Columns panel box. You can add Max Selected(1) to prevent user from selecting multiple columns.
  • Choose Quick Stats panel box. Some sort of "error-handling" if user has no column selected.

 

 

 

 

 

 

Complete script with some modifications:

View more...
Names Default To Here( 1 );
//Clear Symbols(); //dont like using this

If(N Items(Get Data Table List()) == 0,
	Throw("No datatables open. Stopping...");
	stop();
);

//the width of the column list box in pixels
lbWidth = 205;

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

//List of statistics to calculate
StatsList1 = {"Mean", "Std Dev", "Max", "Min", "Range", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N Zero", "Prop 0", "Prop non-0"};

maxStatCount = Max(N Items(StatsList1), N Items(StatsList2), N Items(StatsList3));
//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
	Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
	Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
	Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
	Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
	Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
	Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
	Col N Missing( tempCol )
);
statZero = Expr(
	N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );

//RadioBox() argument
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );

//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
	Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
	Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
	Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
	Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);


//User window
ValueDlg = Expr(
	nwin = New Window( "GUI for quick stats",
		<<Return Result,
		<<On Validate,
		Border Box( Left( 3 ), Top( 2 ),
			V List Box(
				Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ),
				H List Box(
					V List Box(
						Panel Box( "Select Columns",
							//Current calculations might not work correctly if multiple columns are selected. You can use Max Selected(1) to force user to select
							//at maximum 1 column
							ColListData = Col List Box(dt, All, <<Set Data Type( "Numeric" ), Max Selected(1), Grouped, width( lbWidth ), nLines( 10 ), 
								<< On Change( //lazier solution, just set values empty
									scb << Set( {} );
									ncb << Set( {} );
								)
							)
						),
						Panel Box( "Choose quick stats",
							qstats = Radio Box(
								rbArg,
								<<Set Function(
									Function( {this, index},
										{},
										scb << Set( {} );
										ncb << Set( {} );
										vals = this << get;
										tempCol = Column( dt, (ColListData << Get Selected));
										If(!Contains(dt << Get Column Names, tempCol),
											Throw("No column selected"),
											scb << Set( StatList[vals] );
											ncb << Set( StatListRes(vals)[vals])
										);
									)
								)
							)
						)
					),
					Panel Box( "Results",
						//table box properties which can be modified to make it look different is needed
						//<< Set Shade Headings(0), << Set Heading Column Borders(0)
						tb = Table Box(scb = String Col Box( "Stats", {}, << set width(75)), ncb = Number Col Box( "Values", {} ),
							String Col Box("", Repeat({""}, maxStatCount), Visibility("Hidden")) //you can use hidden string col box to "force" height to Table box
						)
					),
					Panel Box( "Action",
						Lineup Box( N Col( 1 ),
							Button Box( "Cancel/End", nwin << Close Window ),
							Text Box( " " ),
							Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) )
						)
					), 

				), 

			), 

		), 

	);

);

ValueDlg;

 

-Jarmo
SDF1
Super User

Re: Help Scripting an Interactive window that updates upon user choices

Hi All,

 

  I'd like to thank you for your ongoing suggested changes. I have made some changes to the script and like the latest modified version better, so I really appreciate other's contributions. The updated script will be posted at the end of this reply. This new script also provides summary statistics for Character data types. I also slightly modified the layout of the panels.

 

  @jthi , I think your suggestions were very good, and I have incorporated them. I like the colored header names for the result statistics. Also, similar to what @ErraticAttack had in their code, I made it so that the stats would update upon selecting a new column OR selecting a new numerical result. I allowed the character stat results to change its vertical size because there might be many levels, like for the Big Class.jmp data table. The categorical stats will also update when changing to that column type, but will throw an error if the character column is selected and then someone clicks on a numerical stat option. I did keep the width suggestion so the window wouldn't keep changing width size. Sorry @ErraticAttack , I'm not so familiar at this point with defining new name spaces and how you went about modifying the code. It does look very useful and a good way to approach things, I just need to learn how to do it correctly.

 

  I'm sure there are other suggestions out there on how to improve this, especially the aesthetics. If so, please post, but be sure to tag me so I know there's been an update to this discussion. Thanks again everyone for your suggested improvements.

 

Thanks!,
DS

 

<JSL> below

//GUI for quickly reporting statistics written by D. Schmidt, ver1.5
//Thanks to JMP User community members: jthi, ian_jmp, and ErraticAttach for helpful suggested changes.
Names Default To Here( 1 );
Clear Symbols();
//the width of the column list box in pixels
lbWidth = 217;

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

//List of statistics to calculate
StatsList1 = {"µ", "σ", "Max", "Min", "Range(Δ)", "N"};
StatsList2 = {"Quantiles", "5%", "25%", "50%", "75%", "95%"};
StatsList3 = {"N", "N Missing", "N 0", "Prop 0", "Prop non-0"};
maxStatCount = Max( N Items( StatsList1 ), N Items( StatsList2 ), N Items( StatsList3 ) );

//RadioBox() arguments
rbArg = Eval List( {Concat Items( StatsList1, ", " ), Concat Items( StatsList2, ", " ), Concat Items( StatsList3, ", " )} );
rbcArg = {"Select for categorical columns"};

//Statistics to Calculate
statMean = Expr( Col Mean( tempCol ) );
statStd = Expr( Col Std Dev( tempCol ) );
statMax = Expr( Col Max( tempCol ) );
statMin = Expr( Col Min( tempCol ) );
statRange = Expr(
	Col Max( tempCol ) - Col Min( tempCol )
);
statN = Expr( Col Number( tempCol ) );
statQ95 = Expr(
	Col Quantile( tempCol, 0.05 )
);
statQ75 = Expr(
	Col Quantile( tempCol, 0.25 )
);
statQ50 = Expr(
	Col Quantile( tempCol, 0.5 )
);
statQ25 = Expr(
	Col Quantile( tempCol, 0.75 )
);
statQ5 = Expr(
	Col Quantile( tempCol, 0.95 )
);
statMiss = Expr(
	Col N Missing( tempCol )
);
statZero = Expr(
	N Items( Loc( tempCol << get as matrix, 0 ) )
);
statProp0 = Expr( statZero / statN );
statPropn0 = Expr( 1 - statProp0 );

CatStats = Expr(
	coltype = tempCol << Get Data type;
	If( coltype == "Character",
		catdist = dt << Distribution( Nominal Distribution( Column( tempCol ) ), Invisible );
		rpt_catdist = catdist << Report;

		lvl = rpt_catdist[String Col Box( 1 )] << Get;
		Count = rpt_catdist[Number Col Box( 1 )] << Get;
		Prob = rpt_catdist[Number Col Box( 2 )] << Get;
		SummNMiss = rpt_catdist[List Box( 7 )][2] << Get Text;
		SummLvl = rpt_catdist[List Box( 8 )][1] << Get text;
		numNMiss = Num( SummNMiss );
		numLvl = Num( SummLvl );
		catdist << Close Window;
	);
	Insert Into( lvl, {"N Missing", "N Levels"} );
	Insert Into( Count, numNMiss );
	Insert Into( Count, numLvl );
);

//List for results
StatList = Eval List( {StatsList1, StatsList2, StatsList3} );
StatListRes1 = Expr(
	Eval List( {statMean, statStd, statMax, statMin, statRange, statN} )
);
StatListRes2 = Expr(
	Eval List( {., statQ95, statQ75, statQ50, statQ25, statQ5} )
);
StatListRes3 = Expr(
	Eval List( {statN, statMiss, statZero, statProp0, statPropn0} )
);
StatListRes = Expr(
	Eval List( {StatListRes1, StatListRes2, StatListRes3} )
);


//User window
ValueDlg = Expr(
	nwin = New Window( "GUI for quick stats",
		<<Return Result,
		<<On Validate,
		Border Box( Left( 3 ), Top( 2 ),
			V List Box(
				Text Box( "Quick Stats Window", <<Set Font Size( 12 ) ),
				H List Box(
					Panel Box( "Select Columns",
						ColListData = Col List Box(
							dt,
							All,
							Grouped,
							Max Selected( 1 ),
							width( lbWidth ),
							nLines( 10 ),
							<<On change(
								lvlcb << Set( {} );
								ccb << Set( {} );
								pcb << Set( {} );
								scb << Set( {} );
								ncb << Set( {} );
								tempCol = Column( dt, (ColListData << Get Selected) );
								If( !Contains( dt << Get Column Names, tempCol ),
									Throw( "No Column Selected" ),
									coltype = tempCol << Get Data type;
									If(
										Coltype == "Numeric",
											vals = qstats << get;
											scb << Set( StatList[vals] );
											ncb << Set( StatListRes( vals )[vals] );,
										Coltype == "Character",
											CatStats;
											lvlcb << Set( lvl );
											ccb << Set( Count );
											pcb << Set( prob );
									);
								);
							)
						)
					),
					Panel Box( "Numerical Results",
						ntb = Table Box(
							scb = String Col Box( "Stats", {}, <<set width( 75 ) ),
							ncb = Number Col Box( "Values", {} ),
							String Col Box( "", Repeat( {""}, maxStatCount ), Visibility( "Hidden" ) ) //you can use hidden string col box to "force" height to Table box
						)
					),
					Panel Box( "Categorical Results",
						ctb = Table Box(
							lvlcb = String Col Box( "Level", {}, <<set width( 70 ) ),
							ccb = Number Col Box( "Count", {} ),
							pcb = Number Col Box( "Prob", {} ),
							String Col Box( "", Repeat( {""}, maxStatCount ), Visibility( "Hidden" ) ) //you can use hidden string col box to "force" height to Table box
						)
					),
					Panel Box( "Action",
						Lineup Box( N Col( 1 ),
							Button Box( "Cancel/End", nwin << Close Window ),
							Text Box( " " ),
							Button Box( "Help", Web( "https://www.jmp.com/en_ch/support/online-help-search.html?q=*%3A*" ) )
						)
					)
				),
				V List Box(
					H List Box(
						Panel Box( "Choose numerical quick stats",
							qstats = Radio Box(
								rbArg,
								<<Set Function(
									Function( {this, index},
										{},
										lvlcb << Set( {} );
										ccb << Set( {} );
										pcb << Set( {} );
										scb << Set( {} );
										ncb << Set( {} );
										vals = this << get;
										If(
											!Contains( dt << Get Column Names, tempCol );, Throw( "No Column Selected" ),
											Coltype != "Numeric", Throw( "Wrong Column Type for Numerical Stats" ),
											tempCol = Column( dt, (ColListData << Get Selected) );
											coltype = tempCol << Get Data type;
											scb << Set( StatList[vals] );
											ncb << Set( StatListRes( vals )[vals] );
										);
									)
								)
							), 

						), 
					)
				)
			), 

		), 

	), 

);


ValueDlg;