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

Create a timeline horizontal bar chart with varying category over time

Hi All,

I have a data table with a bunch of units that fall into different categories for different periods of time.  This data set is defined in the data table as here: There are four columns of data – (i) unit identifier (a discrete number), (ii) start date, (iii) end date and (iv) category.  The category column lists the categories into which the unit falls into between the start and end time.  A given unit can have multiple rows of data corresponding to various periods.  The data table is as attached.

 

I am trying to create a graph – with X axis as the time, Y axis as unit, and for each unit, I need a horizontal bar chart that shows the category by a color for the given time period.  I am attaching a graph sketch to show how the graph should look like.  The sketch is to drive my idea of the graph.

 

I tried my best, but could not get to what I was looking for.  Appreciate your help on this.  Either through a graph builder, or a JSL script is fine.  I am using JMP 16 pro.

1 ACCEPTED SOLUTION

Accepted Solutions
txnelson
Super User

Re: Create a timeline horizontal bar chart with varying category over time

JMP does not have a built in chart to produce what you want.  However, it does have the ability to modify default graphs to get what you want.   So, the JSL I provided before, and have added more annotation to, and listed below uses the Graph Builder Platform, to create the general form for the required graph, but then the script adds graphics to it, that provides the desired results, and deletes the original results.  In my first listing of the script, I just changed the bars produced by the original GB, to be displayed using white.  However, I have changed that to just delete the original bars.  The original bars is what you are seeing in the background of the chart.

Concerning the Legend, it needs to be created.  You need to take on that challenge.  First, you need to study the current script.  Rea

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

// The Graph Builder Platform currently does not have the capability to create the
// needed Gantt like chart.  The main issue is that it does not apppear that Graph
// Builder can display more than one Range Bar on a given line.  If more than one
// range is input, then Graph Builder averages the start values and then averages
// the end values, and creates a range bar with the averaged values.  
// However, Graph Builder does create a display window with the correct Axes etc.
// So the JSL below runs the Graph Builder Platform, and then adds the Gantt like
// bars, and then finally, deletes the original bars that Graph Builder created.
gb = Graph Builder(
	Size( 1121, 626 ),
	Show Control Panel( 0 ),
	Variables(
		X( :Start Date ),
		X( :End Date, Position( 1 ) ),
		Y( :Unit )
	),
	Elements( Bar( X( 1 ), X( 2 ), Y, Legend( 32 ), Bar Style( "Range" ) ) ),
	SendToReport(
		Dispatch(
			{},
			"Start Date",
			ScaleBox,
			{Min( 3790824458.85 ), Max( 3734876513.055 ), Interval( "Week" ), Inc( 1 ), Minor Ticks( 0 ),
			Label Row( Label Orientation( "Angled" ) )}
		),
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				32,
				Level Name( 0, "Span of Task", Item ID( "Mean(Start Date)..Mean(End Date)", 1 ) )
			)}
		),
		Dispatch( {}, "graph title", TextEditBox, {Set Text( "Gantt Chart" )} ),
		Dispatch( {}, "X title", TextEditBox, {Set Text( "Date" )} ),
		Dispatch( {}, "Y title", TextEditBox, {Set Text( "Tasks" )} )
	)
);
// set axis values of the graph to make sure the complete date range is displayed
// Set the min date displayed to the earliest date - 5% of the overall range
// Set the max date displayed to the latest date + 5% of the overall range
offset = (Col Max( :end date ) - Col Min( :end date )) / 20;
gbr = gb << report;
gbr["Graph Builder", AxisBox( 1 )] << Min( Col Min( :start date ) - offset );
gbr["Graph Builder", AxisBox( 1 )] << Max( Col Max( :end date ) + offset );

// Add the color bars to the display
gbr["Graph Builder", FrameBox( 1 )] << Add Graphics Script(
	// Get Category values
	Summarize( dt, catGroups = by( :Category ) );
	
	// Loop through each row in the data table and draw a filled rectangle on the 
	// display
	For Each Row(
		Fill Color( Contains( catGroups, :category ) + 2 );
		Rect( :Start Date, Num( :unit ) - .9, :End Date, Num( :unit ) - 1.1, fill = 1 );
	);
);

// Delete the bars created by Graph Builder
theBarSeg = gbr["Graph Builder", FrameBox( 1 )] << find seg( bar seg);
theBarSeg << delete;

d the Scripting Guide, and familiarize yourself with the Scripting Index.  Then you can take on the building of the legend.

Jim

View solution in original post

3 REPLIES 3
txnelson
Super User

Re: Create a timeline horizontal bar chart with varying category over time

Here is the start of a script that you should be able to expand on.  I ran the Gantt add-on, which doesn't allow for multiple ranges per line, and added some items to the script that does what you want.

txnelson_0-1697894299866.png

Names Default To Here( 1 );
dt = Current Data Table();
gb = Graph Builder(
	Size( 1121, 626 ),
	Show Control Panel( 0 ),
	Variables(
		X( :Start Date ),
		X( :End Date, Position( 1 ) ),
		Y( :Unit/*, Order By( :Start Date, Descending, Order Statistic( "Mean" ) )*/ )
	),
	Elements( Bar( X( 1 ), X( 2 ), Y, Legend( 32 ), Bar Style( "Range" ) ) ),
	SendToReport(
		Dispatch(
			{},
			"Start Date",
			ScaleBox,
			{Min( 3790824458.85 ), Max( 3734876513.055 ), Interval( "Week" ), Inc( 1 ), Minor Ticks( 0 ),
			Label Row( Label Orientation( "Angled" ) )}
		),
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				32,
				Level Name( 0, "Span of Task", Item ID( "Mean(Start Date)..Mean(End Date)", 1 ) ),
				Properties( 0, {Fill Color( 2 )}, Item ID( "Mean(Start Date)..Mean(End Date)", 1 ) )
			)}
		),
		Dispatch( {}, "graph title", TextEditBox, {Set Text( "Gantt Chart" )} ),
		Dispatch( {}, "X title", TextEditBox, {Set Text( "Date" )} ),
		Dispatch( {}, "Y title", TextEditBox, {Set Text( "Tasks" )} )
	)
);
// set axis values
offset = (Col Max( :end date ) - Col Min( :end date )) / 20;
gbr = gb << report;
gbr["Graph Builder", AxisBox( 1 )] << Min( Col Min( :start date ) - offset );
gbr["Graph Builder", AxisBox( 1 )] << Max( Col Max( :end date ) + offset );

// Add the display
gbr["Graph Builder", FrameBox( 1 )] << Add Graphics Script(
	// Get Category values
	Summarize( dt, catGroups = by( :Category ) );
	For Each Row(
		Fill Color( Contains( catGroups, :category ) + 2 );
		Rect( :Start Date, Num( :unit ) - .9, :End Date, Num( :unit ) - 1.1, fill = 1 );
	);
)

;

 

Jim
Velagandula
Level II

Re: Create a timeline horizontal bar chart with varying category over time

Thank you so much!  Your solution is almost exact to what I was looking for.  I could not fully understand how you manipulated the data to get different color bars for each time period.  Here are 2 questions from your script:

1.  How can I show the legend for each category?  on the top right? - like the values A,B,C,D,E etc in the table?  Is it also possible to show them above or inside each color bar for each unit?

2.  I see white colored rectangular spaces behind the colorred bars.  What are they and can I not show them in the graph?

 

Appreciate your help to refine this further.  Thanks a lot!

txnelson
Super User

Re: Create a timeline horizontal bar chart with varying category over time

JMP does not have a built in chart to produce what you want.  However, it does have the ability to modify default graphs to get what you want.   So, the JSL I provided before, and have added more annotation to, and listed below uses the Graph Builder Platform, to create the general form for the required graph, but then the script adds graphics to it, that provides the desired results, and deletes the original results.  In my first listing of the script, I just changed the bars produced by the original GB, to be displayed using white.  However, I have changed that to just delete the original bars.  The original bars is what you are seeing in the background of the chart.

Concerning the Legend, it needs to be created.  You need to take on that challenge.  First, you need to study the current script.  Rea

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

// The Graph Builder Platform currently does not have the capability to create the
// needed Gantt like chart.  The main issue is that it does not apppear that Graph
// Builder can display more than one Range Bar on a given line.  If more than one
// range is input, then Graph Builder averages the start values and then averages
// the end values, and creates a range bar with the averaged values.  
// However, Graph Builder does create a display window with the correct Axes etc.
// So the JSL below runs the Graph Builder Platform, and then adds the Gantt like
// bars, and then finally, deletes the original bars that Graph Builder created.
gb = Graph Builder(
	Size( 1121, 626 ),
	Show Control Panel( 0 ),
	Variables(
		X( :Start Date ),
		X( :End Date, Position( 1 ) ),
		Y( :Unit )
	),
	Elements( Bar( X( 1 ), X( 2 ), Y, Legend( 32 ), Bar Style( "Range" ) ) ),
	SendToReport(
		Dispatch(
			{},
			"Start Date",
			ScaleBox,
			{Min( 3790824458.85 ), Max( 3734876513.055 ), Interval( "Week" ), Inc( 1 ), Minor Ticks( 0 ),
			Label Row( Label Orientation( "Angled" ) )}
		),
		Dispatch(
			{},
			"400",
			ScaleBox,
			{Legend Model(
				32,
				Level Name( 0, "Span of Task", Item ID( "Mean(Start Date)..Mean(End Date)", 1 ) )
			)}
		),
		Dispatch( {}, "graph title", TextEditBox, {Set Text( "Gantt Chart" )} ),
		Dispatch( {}, "X title", TextEditBox, {Set Text( "Date" )} ),
		Dispatch( {}, "Y title", TextEditBox, {Set Text( "Tasks" )} )
	)
);
// set axis values of the graph to make sure the complete date range is displayed
// Set the min date displayed to the earliest date - 5% of the overall range
// Set the max date displayed to the latest date + 5% of the overall range
offset = (Col Max( :end date ) - Col Min( :end date )) / 20;
gbr = gb << report;
gbr["Graph Builder", AxisBox( 1 )] << Min( Col Min( :start date ) - offset );
gbr["Graph Builder", AxisBox( 1 )] << Max( Col Max( :end date ) + offset );

// Add the color bars to the display
gbr["Graph Builder", FrameBox( 1 )] << Add Graphics Script(
	// Get Category values
	Summarize( dt, catGroups = by( :Category ) );
	
	// Loop through each row in the data table and draw a filled rectangle on the 
	// display
	For Each Row(
		Fill Color( Contains( catGroups, :category ) + 2 );
		Rect( :Start Date, Num( :unit ) - .9, :End Date, Num( :unit ) - 1.1, fill = 1 );
	);
);

// Delete the bars created by Graph Builder
theBarSeg = gbr["Graph Builder", FrameBox( 1 )] << find seg( bar seg);
theBarSeg << delete;

d the Scripting Guide, and familiarize yourself with the Scripting Index.  Then you can take on the building of the legend.

Jim