cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Try the Materials Informatics Toolkit, which is designed to easily handle SMILES data. This and other helpful add-ins are available in the JMP® Marketplace
Choose Language Hide Translation Bar
Paul06
Level I

Get column names that has particular value

Hi, 

 

I just started using jmp at work and trying to learn JSL. I am trying to write a script to get the column names where the row value =1. For example, the table shows values of 0 and 1 under different IMCX columns and I want to find out which column has the value =1 in each row and store under a new column called IMC. In the first row,  column IMC 4 has 1 so I manually enter IMC4 under IMC. There are more than 5000 rows in the tables. Thank you for the help. 

 

Paul06_0-1609807451271.png

 

1 ACCEPTED SOLUTION

Accepted Solutions
ThuongLe
Level IV

Re: Get column names that has particular value

You can do somthing like this:

Capture.PNG

 

The formula in Result column is as below:

If( :A == 0,
	"",
	Char( Column Name( 1 ) )
) || If( :B == 0,
	"",
	Char( Column Name( 2 ) )
) || If( :C == 0,
	"",
	Char( Column Name( 3 ) )
) || If( :D == 0,
	"",
	Char( Column Name( 4 ) )
)

I use concatenate keyword to check each column to see if it's a 1.

Let me know if it works out for you!

Thuong Le

View solution in original post

10 REPLIES 10
ThuongLe
Level IV

Re: Get column names that has particular value

You can do somthing like this:

Capture.PNG

 

The formula in Result column is as below:

If( :A == 0,
	"",
	Char( Column Name( 1 ) )
) || If( :B == 0,
	"",
	Char( Column Name( 2 ) )
) || If( :C == 0,
	"",
	Char( Column Name( 3 ) )
) || If( :D == 0,
	"",
	Char( Column Name( 4 ) )
)

I use concatenate keyword to check each column to see if it's a 1.

Let me know if it works out for you!

Thuong Le
Paul06
Level I

Re: Get column names that has particular value

Thank you so much. It worked!
txnelson
Super User

Re: Get column names that has particular value

My read of the initial input is that more than 1 column on a given row may have a value of 1.  If that is not the case, the following 2 scripts are not the method to use.

Here is one way to do this

Names Default To Here( 1 );

// Create a sample data table
dt = New Table( "Example",
	Add Rows( 2 ),
	New Column( "IMCO", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC1", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IIMC2", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC3", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC4", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IMC5", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC6", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ), Set Display Width( 46 ) ),
	New Column( "IMC7", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC8", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC9", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC10", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC11", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "RESIDUAL", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [32.3201037, 20.54947] ) ),
	New Column( "TEST", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [., .] ) )
);

// Generate a list of columns to be processed
colNamesList = dt << get column names(string);
remove from (colNamesList,13,2);

// Find the maximum( the ones ) for the columns in question
dtSum = dt<< Summary(
	Max(colNamesList),
	Freq( "None" ),
	Weight( "None" ),
	statistics column name format( "column" ),
	Link to original data table( 0 )
);

// Stack all of the summarized columns
dtStack = dtSum << Stack(
	columns(
		colNamesList
	),
	Source Label Column( "IMC" ),
	Stacked Data Column( "Data" )
);

close( dtSum, nosave );

// Delete all data that do not have 1 
dtStack << select where(:Data !=1 );
dtStack << delete rows;

// Delete the unwanted columns from the summary table
dtStack << delete columns( {N Rows, data} );

// If there are more rows than in the original table, add rows
if( n rows( dt ) < N Rows( dtStack ),
	dt << add rows( N Rows( dtStack ) - N Rows( dt ) )
);

// Add the column names for the columns found with 1's in their data
dt << Update( With( dtStack ) );

close( dtStack, nosave );





imc.PNG

Here is a second way to do it:  In this example more than one column on a given row has a value of 1

Names Default To Here( 1 );

// Create a sample data table
dt = New Table( "Example",
	Add Rows( 2 ),
	New Column( "IMCO", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC1", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IIMC2", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC3", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ) ),
	New Column( "IMC4", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IMC5", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC6", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ), Set Display Width( 46 ) ),
	New Column( "IMC7", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC8", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC9", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC10", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC11", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "RESIDUAL", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [32.3201037, 20.54947] ) ),
	New Column( "TEST", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [., .] ) ),
	New Column( "IMC", Character, "Nominal", Set Values( {"IMC1", "IMC3"} ) )
);

// Generate a list of columns to be processed
colNamesList = dt << get column names( string );
Remove From( colNamesList, 13, 2 );
foundNamesList = {};

For( i = 1, i <= N Items( colNamesList ), i++,
	theRows = dt << get rows where( As Column( colNamesList[i] ) == 1 );
	If( N Rows( theRows ) > 0,
		Insert Into( foundNamesList, colNamesList[i] )
	);
);

dt << New Column( "IMC", character );

// If there are more rows than in the original table, add rows
If( N Rows( dt ) < N Items( foundNamesList ),
	dt << add rows( N Items( foundNamesList ) - N Rows( dt ) )
);

If( N Items( foundNamesList ) > 0,
	dt:IMC << set values( foundNamesList )
);

imc2.PNG

Jim
jthi
Super User

Re: Get column names that has particular value

My solution (using same sample data table as txnelson):

Names Default To Here( 1 );

// Create a sample data table
dt = New Table( "Example",
	Add Rows( 2 ),
	New Column( "IMCO", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC1", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IIMC2", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC3", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC4", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IMC5", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC6", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ), Set Display Width( 46 ) ),
	New Column( "IMC7", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC8", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC9", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC10", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC11", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "RESIDUAL", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [32.3201037, 20.54947] ) ),
	New Column( "TEST", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [., .] ) )
);

//get wanted columns. Assumes that IMC columns start from column 1 and all IMC columns are one after another
colNames = dt << Get Column Names("String");
For(i = N Items(colNames), i > 0 , i--,
	If(!Starts With(colNames[i], "IMC"),
		Remove From(colNames, i),
		break(); //we can break on first occurance
	);
);

//new column with IMC with value 1
dt << New Column("IMC", Character, 
	<< Set Each Value(
		rowValues = dt[Row(), 0][1::N Items(colNames)]; //get values of row as matrix
		colIndex = Contains(rowValues, 1); //get index of
		If(colIndex > 0, //handle 
			colNames[colIndex], //get column name with the index
			""; //when no 1 found use ""
		);
	);
);

I like the first solution @txnelson  offered due to two (three) reasons:

  1. It is using so many menu items directly found from JMP and you could almost script it without any JSL knowledge by just copy-pasting from datatable Sources
  2. It is using very JSL like syntax with all << select wheres and such
  3. (I think that kind of workflow presented in the solution is very JMP like)
-Jarmo
ian_jmp
Level X

Re: Get column names that has particular value

Regarding "I just started using jmp at work and trying to learn JSL" (and has been implied already) there are many ways to get the job done.

 

So, in this spirit, please find yet another slight variation. Use 'Help > Books > Scripting Guide' to figure out how it works.

Names Default To Here( 1 );

// Create a sample data table
dt = New Table( "Example",
	Add Rows( 2 ),
	New Column( "IMCO", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC1", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IIMC2", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC3", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ) ),
	New Column( "IMC4", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [1, 0] ) ),
	New Column( "IMC5", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC6", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 1] ), Set Display Width( 46 ) ),
	New Column( "IMC7", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC8", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC9", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC10", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
	New Column( "IMC11", Numeric, "Continuous", Format( "Best", 12 ), Set Values( [0, 0] ) ),
);

// Get a list of the column names
colList = dt << getColumnNames("String");

// Get the '0's and '1's into a matrix
mat = dt << getAsMatrix;

// Value to search for
searchVal = 1;

// Add an 'expression' column and loop rowise . . .
newCol = dt << NewColumn("Value "||Char(searchVal)||" found in Column:", Expression);
for (r=1, r<=NRow(dt), r++,
	newCol[r] = colList[Loc(mat[r, 0], searchVal)];
);

 

Paul06
Level I

Re: Get column names that has particular value

Hi Ian, Thanks for your time and explanation. I can understand your code. However, when I ran the script setting dt as current table, I got empty() in the resultant expression column. I have a long way to learn here. Thanks all for your input and suggestions
Paul06
Level I

Re: Get column names that has particular value

Hi Ian,
Spend some time reading the help>Books section and changed the keyword from loc to contains worked now. Thank you ton!

// Get a list of the column names
colList = dt << getColumnNames( "String" );

// Get the '0's and '1's into a matrix
mat = dt << getAsMatrix;

// Value to search for
searchVal = 1;

// Add an 'expression' column and loop rowise . . .
newCol = dt << New Column( "Value " || Char( searchVal ) || " found in Column:", Expression );
for( r = 1, r <= N Row( dt ), r++,
    newCol[r] = colList[Contains( mat[r, 0], searchVal )]
);
Paul06
Level I

Re: Get column names that has particular value

Thank you for your time and help. I was not able to run the script succesfully. It created a column IMC but no value in it. I will debug and try to understand the code better.
doraemengs
Level III

Re: Get column names that has particular value

Hi jthi,

 

if my data looks like this example but all of the columns are numeric (continuous data) and I want to choose the column name with cut off such as > 3000 (in 1 row might have multiple columns > 3000) what should I do on script?
I use the following script

colNames = dt << Get Column Names("String");

For(i = N Items(colNames), i > 3000 , i--,

);

but it did not work. 

 

Best