Hello everyone,
I have a table with a grouping column and several response variables.
New Table( "Test",
Add Rows( 7 ),
New Column( "GROUP",
Character,
"Nominal",
Set Values( {"a", "b", "c", "d", "e", "f", "g"} )
),
New Column( "Y",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [7, ., 6, ., 4, ., 2] )
),
New Column( "Y 2",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [7, 6, 2, 3, ., ., .] ),
Set Display Width( 49 )
)
)
I would like to create a bar chart with a column switcher.
Graph Builder(
Size( 527, 448 ),
Show Control Panel( 0 ),
Variables(
X( :GROUP, Order By( :Y, Ascending, Order Statistic( "Mean" ) ) ),
Y( :Y )
),
Elements( Bar( X, Y, Legend( 4 ) ) ),
Column Switcher( :Y, {:Y, :Y 2} )
)
My problem is that I do not want to display levels with no data. In other words, I do not want to see levels "b", "d" and "f" for Y and levels "e", "f", "g" for Y2.
I tried to use a "where" clause but unfortunately it is not taken into acount by the Column Switcher.
Do you have any idea of how we could do that?
Thanks in advance!
Hi again @anne_sa ,
Sorry for the delay, I actually caught the flu for a few days and got behind a little.
I have attached two files. The first jsl file (Example Script for Changing row states.jsl) is the driver file and the path in the second line is the full path of the location that you place the second file (GraphBuilderJSLAPI.jsl).
//Include script to modify GraphBuilder with some special functions defined
include(ConvertFilePath("/Users/gemann/Projects/Prototypes/JSLClasses/GraphBuilderJSLAPI.jsl", absolute, windows));
//Create a sample table
dt = New Table( "Test",
Add Rows( 7 ),
New Column( "GROUP",
Character,
"Nominal",
Set Values( {"a", "b", "c", "d", "e", "f", "g"} )
),
New Column( "Y",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [7, ., 6, ., 4, ., 2] )
),
New Column( "Y 2",
Numeric,
"Continuous",
Format( "Best", 12 ),
Set Values( [7, 6, 2, 3, ., ., .] ),
Set Display Width( 49 )
)
);
//Add a new window and build a listbox beside a graphbuilder
New Window( "CustomColumnSwitcher Window",
//Start by getting all of the columns in the current datatable
CNames = dt << Get Column Names( Numeric );
Show( CNames );
//User a horizontal layout
HListBox(
//Use a ListBox as the new Column Switcher
lb = List Box(
CNames,
maxSelected(1),
//The next lines specify the script that gets run when an item in listbox is selected
dt << clearrowstates();
newvarname = lb<<getselected();
ReplaceGBXVariable(gb,"GROUP",newvarname);
ReplaceGBYVariable(gb,newvarname);
rs = dt << select where( IsMissing( Column(newvarname)[] ) );
dt << exclude();
),
//Build the original GraphBuilder
gb = Graph Builder(
Size( 527, 448 ),
Show Control Panel( 0 ),
Variables(
X( :GROUP, Order By( :Y, Ascending, Order Statistic( "Mean" ) ) ),
Y( :Y )
),
Elements( Bar( X, Y, Legend( 4 ) ) )
);
// This line is added for the special case of filtering values that are missing from the graph
rs = currentdatatable() << select where(IsMissing(:Y));
dt << exclude();
);
);
Good luck and let me know if you have any issues. Of course these files are not fully tested!!! :)
It'd be cool if column switch has a <<Set Function() message, so you could get full capability out of it while still being able to add on to it.
I totally agree with you @vince_faller, it would be a very nice feature :)
I think I will add it to the JMP Wish List!
Thank you very much for these scripts @geoffrey_mann
It is definitely cleaner than what I did!
There is just one thing that I would like to adapt: each time we select a new variable in the list box, the row status are reset. Thus if some points have been labelled / excluded / colored... we will loose this information and it can be annoying.
Otherwise it matches my expectations so thanks again!
Hi @anne_sa
I'm so glad this helped. It is something I have wanted to do for a while and you gave me the motivation. :)
Also, I agree with you and @vince_faller that a listener or a way to custom behavior around column switcher would be generally useful to those programming their own addins or changing behavior. We do this all of the time in JMP Clinical and JMP Genomics, which is why I gave credit to @kelci_miclaus and @drewfoglia for the code I borrowed.
If only we knew a JMP product manager who could help make this happen. :) Please both of you vote for the feature and it will help with the justification.
As to the final changes, you should have control in your wrapper code you wrote. The API calls are simply meant to replace the X and Y variables. I will keep adding to these functions to help programmers simplify wrapping GraphBuilder so that they may build addins faster. What I am trying to say here is only add functios to update GraphBuilder in the API file so that any "driver" file you use has the selection behavior. Note that I could have put the dt << clearrowstates(); call below the ReplaceGB... calls to organize the changing of row states to the table in one place. Also note that this code is modifying the row states of the main data table instead of using a local filter to modify the GraphBuilder report. You may want to change your approach if you want multiple reports of the data table. But these are just notes and intended as extra information for the future apps you may build with JMP.
Notice the clearrowstates in your driver file:
dt << clearrowstates();
newvarname = lb<<getselected();
ReplaceGBXVariable(gb,"GROUP",newvarname);
ReplaceGBYVariable(gb,newvarname);
rs = dt << select where( IsMissing( Column(newvarname)[] ) );
dt << exclude();
Based on my "simplistic" understanding of what you are trying to do I recommend you simply replace dt << clearrowstates(); with dt << unexclude(); Let me know if that is the behavior that you prefer or if it is more complex than that.
Hi @geoffrey_mann ,
Thank you for your involvement and the additional informations.
I will start advertising the feature to my colleagues to get votes! :)
Regarding the script, I prefer not affecting the current table so I think the local data filter is a good option! I will explore this possibility deeper.