cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Discussions

Solve problems, and share tips and tricks with other JMP users.
Choose Language Hide Translation Bar
hogi
Level XIII

Value Colors from another column

Hi @Jordan_Hiller , it was nice to meet you at the Discovery Summit 2025 (online) 

 

An issue I still suffer with:
How to assign colors to line plots, especially when line is used in combination with smoother:
Graph Builder. Combine Smoother and Line - how? 

hogi_0-1758860224150.png

I wished this option was available in JMP: Graph Builder: Line - possibility to add breaks 

or this one: Graph Builder - Overlay by multiple columns 

 

 


Here is another interesting task - transferred to Big Class:

 

  • I want to apply colour to a large number of curves.
    So, let's use the students of big class and plot name  (39 values!) on the x-axis.
    Imagine that the bars are actually line plots in different colors.
  • I don't want to see all the data at once, but "zap" through the data - age by age
    so let's add a data filter to restrict the view to a specific age
  • The task: In this view, every (visible) student should be represented by a unique color.
    please remember: the bar graph will be complicated curves. So, we don't want 2 curves in a plot with the same color.

    We can use the new col score() which was introduced in JMP19:New in Graph Builder for JMP 19 
    so helpful! - so easy to use! - a huge benefit!
    We sort the students within an age group alphabetically
    [ the 1st students are:  Jaclyn (age:12), Alice (age: 13) , the second ones: James & Barbara ...]

    This Score can be used to assign a unique color: different score - different color.

Now, when we cycle through the age groups, we see: 
no duplicate colors in any of the age groups  hogi_0-1758875289309.png  (indeed, we can use a better color scale with more distinct colors : )

Color_by_ColScore.gif

So far: great! Now, let's address the problem.

For this plot, you can disable the legend as it provides little benefit — it just shows the value of the auxiliary column 'col score'.

Here, the students are clearly visible on the x-axis.

 

However, this is just a dummy graph. In reality, the x-axis has to be used for a continuous variable and, instead of boring bar graphs, we have complicated curves. The only way to identify the 'students' is via the legend.

 

So, how can the color settings be transferred from the auxiliary column 'col score' to the 'name' column, such that the legend makes sense?


Any suggestions or alternatives are highly welcome.

 

Names Default To Here( 1 );
dt = Open( "$SAMPLE_DATA/Big Class.jmp" );
{uniqueColor} = dt << New Formula Column(
	Operation( Category( "Aggregate" ), "Score Unique" ),
	Columns( :name ),
	Group By( :age )
);
uniqueColor<< set name ("uniqueColor");
Graph Builder(
	Variables( X( :name ), Color( :uniqueColor ) ),
	Elements( Bar( X, Legend( 3 ) ) ),
	Local Data Filter( Add Filter( columns( :age ), Where( :age == 12 ) ) )
);

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
hogi
Level XIII

Re: Value Colors from another column

via Scripting:

fromCol = Name Expr( :uniqueColor );
toCol = Name Expr( :name );

steal my colors( Name Expr( fromCol ), Name Expr( toCol ) )

// helper labels to sort the entries in the legend by age (not needed with a data filter)
students= set unique(:name << get values()); myValueLabels =Transform each({student}, students, Eval Expr((Expr(student) = Expr(Char(:age[where(dt,:name == student)[1]])||"_"||student))) ); dt:name << Value Labels( myValueLabels ) << Use Value Labels( 1 );

 

 

hogi_0-1759077024674.png

 

 

steal my colors: 

steal my colors = Function( {fromCol, toCol}, // fromCol and toCol are "Columns"
	//{default local}, 
	
	write("from column  ", Name Expr( fromCol ), "\!n");
	write("to           ", Name Expr( toCol ) , "\!n");




// Lookup: Name -> UniqueColorID
	Eval(
		Eval Expr(
			Lookup = Current Data Table() << Summary(
				Group( Expr( Name Expr( toCol ) ) ),
				Mean( Expr( Name Expr( fromCol ) ) ),
				statistics column name format( "column" )
			)
		)
	);
	
	// grey values for duplicates (like Robert)
	duplicates = As Column( Lookup, 1 )[Where( Lookup, :N Rows > 1 )]; // AsColumn(Lookup,1), not toCol?!? toCol lives in dt !
	If(N items(duplicates),ColorsDuplicates =  Transform Each( {duplicate}, As List( Index( 1, N Items( duplicates ) ) ),
		{255, 255, 255} - duplicate / N Items( duplicates ) * {255, 255, 255}
	));
	
	// Lookup: label -> uniqueColorID
	AA1 = Associative Array( lookup[0, {1, 3}] ); // 1: label , 3: uniqueColorID
	labels = AA1 << get keys;
	Close(Lookup, noSave);

	// workaround: assign colors to "fromCol" and get them via the column script
	// (because I don't know how to get the Nth color from a Color Theme on my own)
	Eval(
		Eval Expr(
			dt << Color or Mark by Column(
				Expr( Name Expr( fromCol ) ),
				Color Theme( "JMP Blue Red Green" ),
				Marker( 0 ),
				Continuous Scale( 0 ),
				Save To Column Property( 1 )
			)
		)
	);
	myScript = fromCol << get script;

// convert colors from a column property
	ValueColorsProperty = Extract Expr( myScript, Set Property( "Value Colors", Wild List() ) );
// ... into an Associative Array for the Lookup: uniqueColorID -> color
	AA2 = Associative Array( Substitute( Arg( ValueColorsProperty, 2 ), Expr( Assign() ), Expr( List() ) ) );

// for each label, define a color
	assignments = Transform Each( {label}, labels,
		duplicateID = Contains( duplicates, label );
		
		Eval Expr( // don't execute, just evaluate the left and right part
			Expr( label ) = Expr(
				If( duplicateID, // duplicate Label? -> grey value
					ColorsDuplicates[duplicateID]
				, 
	
					AA2[AA1[label]]
				) // otherwise: look it up via the associative arrays
			)
		);
	);

// assign the settings to the target column
	toCol << Set Property( "Value Colors", assignments );

);

 

 

View solution in original post

7 REPLIES 7

Re: Value Colors from another column

Hi @hogi ,

 

Another cool thing you can do in JMP is use the tags to assign column properties like colour values, that way unique colours are assigned and you don't see any duplicates - you can take that tag over to different properties too.

 

Ben_BarrIngh_0-1758873357684.png

Cheers,

Ben

 

“All models are wrong, but some are useful”
hogi
Level XIII

Re: Value Colors from another column

Hi Ben, this is what I do in general - but I don't see a way how it can help here.

How can I use Value Colors for this use case? What is your suggestion?

 

Some details which might help to understand the issue.

The tricky thing:
in the columns properties of "name" I have close to 0 chance to assign meaningful colors to 40 students such that the above mentioned task can be fulfilled.

 

This is why I developed the intermediate step with the Col Score values.

But when I assign specific colors in the auxiliary column Col Score, the legend won't show the names of the students.
So: dead end?

Sore, with scripting, I can map the groups from  Col Scores to Colors for column "name". 

But is there a more elegant solution? Maybe even without the need of Col Score?

Re: Value Colors from another column

Hello Holger, it was great to see you at the Online Discovery Summit!

 

I have a hacky approach you can try for the first problem -- it involves splitting the data by the groups. I had to do some manual management of the colors, but it wasn't too bad.

 

linesmoothcolors.png

 

I didn't understand your second problem -- perhaps you could supply an example with the curves at issue, rather than bars.

 

Cheers,

Jordan

 

 

Names Default To Here( 1 );

dt = Open( "$SAMPLE_DATA/Functional Data/Weekly Weather Data.jmp" );
dt << New Column( "group", Character, "Nominal", Formula( Substr( :STATION, 8, 1 ) ) );

dt << New Column( "DupGroup", Character, "Nominal", Formula( :group ) ) << Run Formulas;

    //Split data table
dt2 = dt << Split(
	Split By( :group ),
	Split( :TAVG ),
	Group( :DATE, :STATION ),
	Output Table( "SplitByStationDate" ),
	Remaining Columns( Keep( :DupGroup ) ),
	Sort by Column Property
);

dt2 << Graph Builder(
	Size( 636, 564 ),
	Show Control Panel( 0 ),
	Fit to Window( "Off" ),
	Variables(
		X( :DATE ),
		Y( :"2"n ),
		Y( :"3"n, Position( 1 ) ),
		Y( :"4"n, Position( 1 ) ),
		Overlay( :STATION, Overlay Encoding( "None" ) ),
		Color( :DupGroup )
	),
	Elements(
		Line( X, Y( 1 ), Y( 2 ), Y( 3 ), Legend( 6 ) ),
		Smoother( X, Y( 1 ), Y( 2 ), Y( 3 ), Overlay( 0 ), Color( 0 ), Legend( 7 ) )
	),
	SendToReport(
		Dispatch( {}, "400", ScaleBox,
			{Legend Model(
				6,
				Properties( 0, {Line Color( 21 )}, Item ID( "2", 1 ) ),
				Properties( 1, {Line Color( 19 )}, Item ID( "3", 1 ) ),
				Properties( 2, {Line Color( 20 )}, Item ID( "4", 1 ) ),
				Properties( 3, {Line Color( 19 )}, Item ID( "2 (STATION=USW00003195)", 1 ) ),
				Properties( 4, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00003195)", 1 ) ),
				Properties( 5, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00003195)", 1 ) ),
				Properties( 6, {Line Color( 19 )}, Item ID( "2 (STATION=USW00003868)", 1 ) ),
				Properties( 7, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00003868)", 1 ) ),
				Properties( 8, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00003868)", 1 ) ),
				Properties( 9, {Line Color( 19 )}, Item ID( "2 (STATION=USW00003949)", 1 ) ),
				Properties( 10, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00003949)", 1 ) ),
				Properties( 11, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00003949)", 1 ) ),
				Properties( 12, {Line Color( 21 )}, Item ID( "2 (STATION=USW00012924)", 1 ) ),
				Properties( 13, {Line Color( 21 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00012924)", 1 ) ),
				Properties( 14, {Line Color( 21 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00012924)", 1 ) ),
				Properties( 15, {Line Color( 19 )}, Item ID( "2 (STATION=USW00013733)", 1 ) ),
				Properties( 16, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00013733)", 1 ) ),
				Properties( 17, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00013733)", 1 ) ),
				Properties( 18, {Line Color( 19 )}, Item ID( "2 (STATION=USW00013877)", 1 ) ),
				Properties( 19, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00013877)", 1 ) ),
				Properties( 20, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00013877)", 1 ) ),
				Properties( 21, {Line Color( 20 )}, Item ID( "2 (STATION=USW00014751)", 1 ) ),
				Properties( 22, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00014751)", 1 ) ),
				Properties( 23, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00014751)", 1 ) ),
				Properties( 24, {Line Color( 20 )}, Item ID( "2 (STATION=USW00014922)", 1 ) ),
				Properties( 25, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00014922)", 1 ) ),
				Properties( 26, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00014922)", 1 ) ),
				Properties( 27, {Line Color( 20 )}, Item ID( "2 (STATION=USW00024024)", 1 ) ),
				Properties( 28, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00024024)", 1 ) ),
				Properties( 29, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00024024)", 1 ) ),
				Properties( 30, {Line Color( 20 )}, Item ID( "2 (STATION=USW00024144)", 1 ) ),
				Properties( 31, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00024144)", 1 ) ),
				Properties( 32, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00024144)", 1 ) ),
				Properties( 33, {Line Color( 19 )}, Item ID( "2 (STATION=USW00053182)", 1 ) ),
				Properties( 34, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00053182)", 1 ) ),
				Properties( 35, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00053182)", 1 ) ),
				Properties( 36, {Line Color( 21 )}, Item ID( "2 (STATION=USW00092811)", 1 ) ),
				Properties( 37, {Line Color( 21 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00092811)", 1 ) ),
				Properties( 38, {Line Color( 21 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00092811)", 1 ) ),
				Properties( 39, {Line Color( 19 )}, Item ID( "2 (STATION=USW00093067)", 1 ) ),
				Properties( 40, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00093067)", 1 ) ),
				Properties( 41, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00093067)", 1 ) ),
				Properties( 42, {Line Color( 19 )}, Item ID( "2 (STATION=USW00093242)", 1 ) ),
				Properties( 43, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00093242)", 1 ) ),
				Properties( 44, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00093242)", 1 ) ),
				Properties( 45, {Line Color( 19 )}, Item ID( "2 (STATION=USW00093718)", 1 ) ),
				Properties( 46, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00093718)", 1 ) ),
				Properties( 47, {Line Color( 19 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00093718)", 1 ) ),
				Properties( 48, {Line Color( 20 )}, Item ID( "2 (STATION=USW00094626)", 1 ) ),
				Properties( 49, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "3 (STATION=USW00094626)", 1 ) ),
				Properties( 50, {Line Color( 20 ), Line Style( "Solid" )}, Item ID( "4 (STATION=USW00094626)", 1 ) )
			), Legend Model(
				7,
				Type Properties( 0, "H Line", {Line Width( 5 )} ),
				Properties( 0, {Line Color( 21 ), Line Width( 5 )}, Item ID( "Smooth(2)", 1 ) ),
				Properties( 1, {Line Color( 19 ), Line Width( 5 )}, Item ID( "Smooth(3)", 1 ) ),
				Properties( 2, {Line Color( 20 ), Line Width( 5 )}, Item ID( "Smooth(4)", 1 ) )
			)}
		)
	)
);


 

hogi
Level XIII

Re: Value Colors from another column

Wow, that's one of the best workarounds yet!
:)very creative!
could you please post it in the other conversation. I will accept as a "solution" ...

 

 

hogi
Level XIII

Re: Value Colors from another column

concerning "color"


I thought: should be super easy - with the new Overlay Encoding setting new in JMP18):
don't let it destroy the colors 

with one column on the y axis: works like a charm

hogi_0-1758916543527.png

 

same setting with 2 columns on the y axis: !?!??!

hogi_1-1758916669228.png

 

 

hogi
Level XIII

Re: Value Colors from another column

For the above problem, I have thought that I have a "hacky" solution:

concatenate age and name
the age in front of the name is acceptable for me in the legend:

hogi_1-1758917360631.png

 


and with the age in front, the labels are in an nice order - such that it's possible for the user to apply color gradients to blocks of age groups via Gradient between selected points.

hogi_0-1758917970163.png


but Gradient between selected points is exactly what it says: a gradient between the (colors) of the selected points  - it does not apply the default color theme : (

One could write a wish to extend the functionality of the menu: versatile batch color assignment
select some points - select a color theme - apply the theme to the selected points

I am sure: The wish stays there for years - gets some Kudos - little chance to get implemented.
So, I won't submit.

hogi
Level XIII

Re: Value Colors from another column

via Scripting:

fromCol = Name Expr( :uniqueColor );
toCol = Name Expr( :name );

steal my colors( Name Expr( fromCol ), Name Expr( toCol ) )

// helper labels to sort the entries in the legend by age (not needed with a data filter)
students= set unique(:name << get values()); myValueLabels =Transform each({student}, students, Eval Expr((Expr(student) = Expr(Char(:age[where(dt,:name == student)[1]])||"_"||student))) ); dt:name << Value Labels( myValueLabels ) << Use Value Labels( 1 );

 

 

hogi_0-1759077024674.png

 

 

steal my colors: 

steal my colors = Function( {fromCol, toCol}, // fromCol and toCol are "Columns"
	//{default local}, 
	
	write("from column  ", Name Expr( fromCol ), "\!n");
	write("to           ", Name Expr( toCol ) , "\!n");




// Lookup: Name -> UniqueColorID
	Eval(
		Eval Expr(
			Lookup = Current Data Table() << Summary(
				Group( Expr( Name Expr( toCol ) ) ),
				Mean( Expr( Name Expr( fromCol ) ) ),
				statistics column name format( "column" )
			)
		)
	);
	
	// grey values for duplicates (like Robert)
	duplicates = As Column( Lookup, 1 )[Where( Lookup, :N Rows > 1 )]; // AsColumn(Lookup,1), not toCol?!? toCol lives in dt !
	If(N items(duplicates),ColorsDuplicates =  Transform Each( {duplicate}, As List( Index( 1, N Items( duplicates ) ) ),
		{255, 255, 255} - duplicate / N Items( duplicates ) * {255, 255, 255}
	));
	
	// Lookup: label -> uniqueColorID
	AA1 = Associative Array( lookup[0, {1, 3}] ); // 1: label , 3: uniqueColorID
	labels = AA1 << get keys;
	Close(Lookup, noSave);

	// workaround: assign colors to "fromCol" and get them via the column script
	// (because I don't know how to get the Nth color from a Color Theme on my own)
	Eval(
		Eval Expr(
			dt << Color or Mark by Column(
				Expr( Name Expr( fromCol ) ),
				Color Theme( "JMP Blue Red Green" ),
				Marker( 0 ),
				Continuous Scale( 0 ),
				Save To Column Property( 1 )
			)
		)
	);
	myScript = fromCol << get script;

// convert colors from a column property
	ValueColorsProperty = Extract Expr( myScript, Set Property( "Value Colors", Wild List() ) );
// ... into an Associative Array for the Lookup: uniqueColorID -> color
	AA2 = Associative Array( Substitute( Arg( ValueColorsProperty, 2 ), Expr( Assign() ), Expr( List() ) ) );

// for each label, define a color
	assignments = Transform Each( {label}, labels,
		duplicateID = Contains( duplicates, label );
		
		Eval Expr( // don't execute, just evaluate the left and right part
			Expr( label ) = Expr(
				If( duplicateID, // duplicate Label? -> grey value
					ColorsDuplicates[duplicateID]
				, 
	
					AA2[AA1[label]]
				) // otherwise: look it up via the associative arrays
			)
		);
	);

// assign the settings to the target column
	toCol << Set Property( "Value Colors", assignments );

);

 

 

Recommended Articles