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

Replace 0 values with dot "Value Missing"

How can I alter a data table to turn values which are set as 0 to dot, I found the script for changing dot to zero but not the alternative.

 

Thanks,

 

4 REPLIES 4
jthi
Super User

Re: Replace 0 values with dot "Value Missing"

I would suggest taking a look at this post Should you Loop through a data table or use Recode, or use Get Rows Where to change values in a data... (and the original post) and the discussion there. If I remember correctly the point there was to replace 999 with missing value. The basic idea is usually to loop over rows or columns and replace values.

-Jarmo
txnelson
Super User

Re: Replace 0 values with dot "Value Missing"

Here is one way of converting all of the "0" to a missing value, for a column named "A";

Names Default To Here( 1 );
dt = Current Data Table();

theRows = dt << get rows where( :A == 0 );
Try( :A[theRows] = . );
Jim
vince_faller
Super User (Alumni)

Re: Replace 0 values with dot "Value Missing"

If you're trying to do the whole table you could jsut do

 

Names default to here( 1 );
dt = open("$SAMPLE_DATA\Big Class.jmp");


dt:weight[[1, 5, 6, 8]] = 0; // just setting them to 0
dt:height[[11, 15, 16, 18]] = 0;


wait(2);
// this is the bit you'll want
numeric_cols = dt << Get Column Names("Numeric", "string");
m = dt[0, numeric_cols]; // get the values as a matrix;
m[Loc(m==0)]=.; // set them to missing
dt[0, numeric_cols] = m; // set the data to the matrix
Vince Faller - Predictum
mikedriscoll
Level VI

Re: Replace 0 values with dot "Value Missing"

Good timing. I was just working on some related code last week, doing some execution time reduction, and wanted to add to what was already said.  Going from looping through rows and replacing with the matrix method  (which Vince references above) in one script improved the execution time by around 20x-25x.  On another script, changing from get rows where() to the matrix method improved it by almost 2x. While I was doing it, I wrote the code below so I could share or reference it later, and it seems reasonable to post it here. Note that using the Loc() with lists from character columns uses different syntax and you can't build the more complex logic like you can with all-matrix variables that you get from numeric columns. So I used a technique shared by Craige Hales (linked here) which uses associative arrays and the intersection function. Hope  you find it useful. 

 

Note this script adds new character columns and puts comments in there because I wrote it for demo purposes. Given the original question here, you could just replace the assignment lines such as c3[rowsMale] = "Male";  with column(dtData, "age")[rowsMale] = .; or similar.

 

names default to here(1);
dtData = Open( "$SAMPLE_DATA/Big Class.jmp" );

mAge = column(dtData, "age") << get values();			//a matrix
mHeight = column(dtData, "height") << get values();		//a matrix
lSex = column(dtData, "sex") << get values();			//a list
lName = column(dtData, "name") << get values();			//a list

//note the results of the Loc() function will return a matrix that corresponds to the rows that match the criteria
rowsTall = Loc(mHeight > 63); // simple comparison in Loc() function. c1 = new column("Comments 1","Character"); c1[rowsTall] = "Tall"; rowsTallAndOver13 = Loc( (mHeight > 63) & (mAge > 13)); // can build more complex logic in Loc() function c2 = new column("Comments 2","Character"); c2[rowsTallAndOver13] = "Tall and 14 or older"; rowsMale = Loc(lSex, "M"); // note syntax is slightly different with Loc() for lists when dealing with character columns. //rowsMaleNamedRobert = Loc((lSex, "M"), (lName, "Robert")); // Cannot build complex comparisons with Character columns, see below on the intersection and AA's c3 = new column("Comments 3","Character"); c3[rowsMale] = "Male"; //rowsTall17M = Loc((mHeight > 63) & (mAge == 17) & (lSex == "M") ); // attempt at building complex logic but the syntax is not correct, and can't have lists in a compound comparison //rowsTall17M = Loc((mHeight > 63) & (mAge == 17) & (lSex, "M") ); // attempt at building complex logic. Syntax is closer to correct, but can't have lists in a compound comparison
//Build numeric comparisons all at once, then do character comparisons one at a time. Only 1 character comparison shown here. rowsTall17 = Loc((mHeight > 63) & (mAge == 17) ); // Build the numeric parts separate from char column(s) rowsMale = Loc(lSex, "M"); // Character columns separately. Seems you need one variable per character column, and then intersect them all later.
//insert above into associative arrays, use intersection function to get the matrices intersection aa_rowsTall17 = associative array(rowsTall17); aa_rowsMale = associative array(rowsMale); intersection = aa_rowsMale; // copy of aa_rowsMale, as intersection gets modified in next line intersection<<intersect(aa_rowsTall17); // aa_rowsMale gets modified here with the resulting intersection output, but is still an associative array rowsTall17M = matrix(intersection << get keys); // output here is the intersection of the original two matrices prior to putting them in the AA c4 = new column("Comments 4","Character"); c4[rowsTall17M] = "Tall, Male, 17"; //achieves the same result as what you see above in "comments 4" column but I have found variations of this to be very slow in large data tables. gRowsTallM17 = dtData << get rows where( (:age == 17) & (:sex == "M") & (:height > 63) ); c5 = new column("Comments 5 - using get rows where","Character"); c5[gRowsTallM17] = "Tall, Male, 17";