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

Portion of script not executing unless run after the fact

I have a portion of script I am using to recode columns in my table to change values from "X"s to 0. I got this portion of code to work (Thank you JMP Discussion Forums!!) when run separately from my main script. However, when I insert this into a larger script (even when at the very end) JMP does not execute my command. When the code was placed in the middle of my script everything after it did not run... so I moved it to the bottom of my main script but it still does not execute. Every time I highlight this portion and run it after the fact it does exactly what I want.

 

I tried implementing the wait(0);, changing from i to k, and using a Try statement as well around the For Each Row, but no luck. I am really scratching my head as to why it would only work after the fact. Suggestions?

//Recode columns in Yield Table to give "0" instead of X's
wait(0);
yieldcols = Yields << get column names;
For Each Row( For( k = 1, k <= N Items( yieldcols ), k++, 
	If( Is Missing( As Column( yieldcols[k] )[] ), 
	As Column( yieldcols[k] )[] = 0 ) ) );
9 REPLIES 9

Re: Portion of script not executing unless run after the fact

//Recode columns in Yield Table to give "0" instead of X's
yieldcols = Yields << get column names;

For( col = 1, col <= N Items( yieldcols ), col++,
	For Each Row( If( Is Missing( As Column( yieldcols[k] )[] ), As Column( yieldcols[k] )[] = 0 ) )
);
saneal
Level III

Re: Portion of script not executing unless run after the fact

Just gave it a try. This does not work, even when run separately. The original script I have works, but only when run separately (after the fact, after the entire script is run and I Ctrl+R that one section).

Re: Portion of script not executing unless run after the fact

//Recode columns in Yield Table to give "0" instead of X's
yieldcols = Yields << get column names;

For( col = 1, col <= N Items( yieldcols ), col++,
	For Each Row( If( Is Missing( As Column( yieldcols[col] )[] ), As Column( yieldcols[col] )[] = 0 ) )
);
saneal
Level III

Re: Portion of script not executing unless run after the fact

Hi Mark. This runs separately now but does not work as a smaller part of my larger script. I am wondering if this is less of a scripting issue - more of another problem. Why would a section of code work when run by itself vs. fail when run as a smaller part of a larger script (even when executed last as it would be in first scenario)?

Re: Portion of script not executing unless run after the fact

Hi,

 

If performance on large tables is a concern, you may wish to try the following (note, I used dt as the table name). On a moderate table (100,000 rows x 5 columns) the performance difference is noticeable on my machine, at 0.0056 seconds vs. 0.8261 seconds. This is for a couple of reasons:

 

First, the Loc ( ) and Is Missing ( ) functions are fast, even when used on an entire column at once, which is what we're doing here. That is, dt[0, i] retrieves the entirety of column i.

 

Additionally, by directly indexing the columns, we don't have to deal with getting their names, or retrieving them from the list containing them.

 

Cheers,

Brady

 

Names Default To Here(1);

//create a table with roughly 10% missingness
dt = astable(J(1e5,5,randominteger(1, 20)/(randomuniform() > 0.1)));

For( i = 1, i <= N Col( dt ), i++,
	dt[Loc( Is Missing( dt[0, i] ) ), i] = 0
);

 

 

 

 

 

Re: Portion of script not executing unless run after the fact

Also, let me be the first to admit I never use For Each Row().

 

Ever.

 

Not even if kids eat free.

 

If I must loop over rows (which I try to avoid, by grabbing a column's values all at once either by directly indexing as we I do in this example, by using << get values and operating the resulting list or matrix, etc.), I write a proper for ( ) loop.

 

I'm not saying that For Each Row ( ) never works. I am saying that it comes with caveats, and I don't know what these caveats are. So I avoid For Each Row ( ) like the plague and recommend others do the same, unless they both 1) are willing to learn the caveats, and 2) are willing to assume that those who edit, maintain or otherwise interact with the code in the future will do likewise.

 

The latter is so unlikely that I've never considered undertaking the former.

 

Cheers,

Brady

 

for (i =1, i<=nrow(dt), i++,
   //do some stuff
);

 

Re: Portion of script not executing unless run after the fact

Also, if you have may rows or columns, bind nrows (dt) or ncols (dt) to a variable and use that as the upper index, so nrow(dt) or ncol(dt) does not need to be evaluated each iteration.

 

nc = ncol (dt);

for (i = 1, i<=nc, i++,
 //do some stuff
);

JMP 16 lets you do this with a for each( ) loop, not to be confused with for each row( ). For Each( ) has some other advantages over basic for( ) loops, like local scoping of variables and faster execution in some cases. If you are using JMP 16, be sure to check it out.

 

for each ( { i }, 1::nrow( dt ), 
   //do some stuff
);

 

saneal
Level III

Re: Portion of script not executing unless run after the fact

Hello Brady, 

 

I appreciate all the advice and help. However, this section of code you provided does not seem to be working for me (after changing the table name). I find that very odd - I see no reason why it wouldn't work. Any ideas?

For( i = 1, i <= N Col( Yields ), i++,
	Yields[Loc( Is Missing( Yields[0, i] ) ), i] = 0
);

To rephrase my question a bit: the code I have currently works when run separately, but not when run as a small section of a larger code. I find that odd in itself. I am fine with changing my code, its just that to me that doesn't seem to be what the problem is - because (though not "perfect") it does work! Could this be a bug? Or are there ways to troubleshoot this issue? I have no errors when debugging either. 

Re: Portion of script not executing unless run after the fact

Hi,

 

I am not sure why the code I provided is not working for you. You might try the following:

 

1) Run the original code I provided, alone, in a new window. Does it work? If not, what version of JMP are you using? Direct data table indexing was added a few versions ago, but isn't in JMP 12, for example.

 

2) Assuming 1) above works, the next step is to replace all instances of "dt" with "yields", run the new code alone in the new window. This worked for me and I expect it to work for you if 1) worked for you.

Names Default To Here(1);

//create a table with roughly 10% missingness
yields = astable(J(1e5,5,randominteger(1, 20)/(randomuniform() > 0.1)));

For( i = 1, i <= N Col( yields ), i++,
	yields[Loc( Is Missing( yields[0, i] ) ), i] = 0
);

3) If the data in your table is formula-based, the formulas may have been "written" to the column, but may not be finished evaluating, by the time the JSL intended to fix the missings begins to execute. Make sure all formulas are completely updated, before the code runs, by preceding the code with this line:

Yields << run formulas;

4) Make sure that "Yields" is not referencing anything else other than the data table of interest... not a column name, another variable name, a table variable, etc. For this reason, as a best practice I recommend using "dt" somewhere in any variable name used to point to a table; while it is easy to envision overwriting a table handle "Yields" by inadvertently naming a matrix or vector of values "Yields", it is much less likely to accidentally name such a matrix or vector "YieldDt". However, since your program works if you pause execution, I do not believe this is the issue.

 

If 1) and 2) work for you and neither 3) nor 4) fix the issue, I will need more information to help you: a sample, sanitized table and a snippet of code that can be run against that table to show that the replacement isn't working on that table.

 

Cheers,

Brady