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

How do I make start/stop bar charts?

BHarris
Level VI

Suppose I have this data:

 

StepStartStop
mixer02
heater1112.3
injector144.5
mixer68
heater210.313
injector11212.5
heater11625.4
mixer1820
heater223.430
mixer2426
fan2445
mixer3040

 

... and I want to make this plot (just the bars):

 

BHarris_0-1741904391068.png

 

Is that possible with GraphBuilder?  (note this image is a mockup with PowerPoint)

15 REPLIES 15
Victor_G
Super User


Re: How do I make start/stop bar charts?

Hi @BHarris,

 

I'm not able to reproduce directly what you present in powerpoint, but I may have something similar enough to what you intend to have :

Victor_G_0-1741945282248.png

Unlike your image, the different ranges are not completely aligned, as I need to have a unique identifier for each values range. 
I think the bars could be enlarged for better readability.

You can have a look at the script in the attached datatable.


EDIT: Using a ID column with less levels, the bar graph looks better :

Victor_G_0-1741962832197.png

Both graph scritps are saved in the attached datatable.

 

Victor GUILLER

"It is not unusual for a well-designed experiment to analyze itself" (Box, Hunter and Hunter)
hogi
Level XII


Re: How do I make start/stop bar charts?

Nice approach : )

As an alternative to Overlay, one could also use the ID nested on the Y axis:

hogi_0-1741979753812.png

 

BHarris
Level VI


Re: How do I make start/stop bar charts?

Both of these options create a lot of whitespace because each on/off gets its own horizontal row, and there can be a lot of on/offs in my use-case.  The bar-plots have a red-triangle "overlap" setting that seems like it should work, but even at "Full" it doesn't seem to do anything, so I was hoping there might be a hidden option or a JSL approach that would keep the bars aligned vertically.

jthi
Super User


Re: How do I make start/stop bar charts?

There are many JSL options for something like this. Set Marker Expr would most likely be the best if you can figure how that is used (it doesn't really have documentation). Here is my quick take using Set Marker Draw Expr, this can be made simpler using just one marker but having two lets user "select" the row from both ends

Names Default To Here(1);

dt = New Table("Untitled 2",
	Add Rows(12),
	Compress File When Saved(1),
	New Column("Step",
		Character,
		"Nominal",
		Set Property("Value Colors", {"fan" = -15113984, "heater1" = -5682409, "heater2" = -40563, "injector1" = -29362, "mixer" = -13983232}),
		Set Values({"mixer", "heater1", "injector1", "mixer", "heater2", "injector1", "heater1", "mixer", "heater2", "mixer", "fan", "mixer"})
	),
	New Column("Start",
		Numeric,
		"Continuous",
		Format("Best", 12),
		Set Values([0, 1, 4, 6, 10.300000000000001, 12, 16, 18, 23.399999999999999, 24, 24, 30])
	),
	New Column("Stop",
		Numeric,
		"Continuous",
		Format("Best", 12),
		Set Values([2, 12.300000000000001, 4.5, 8, 13, 12.5, 25.399999999999999, 20, 30, 26, 45, 40])
	)
);
dt << Color or Mark by Column(:Step, Color(1), Marker(0));

gb = dt << Graph Builder(Variables(X(:Start), X(:Stop, Position(1)), Y(:Step), Color(:Step)),
	Elements(Points(X(1), X(2), Y, Legend(7))),
	SendToReport(
		Dispatch({}, "400", ScaleBox,
			{Legend Model(
				7,
				Properties(0, {Marker("FilledSquare")}, Item ID("fan", 1)),
				Properties(1, {Marker("FilledSquare")}, Item ID("heater1", 1)),
				Properties(2, {Marker("FilledSquare")}, Item ID("heater2", 1)),
				Properties(3, {Marker("FilledSquare")}, Item ID("injector1", 1)),
				Properties(4, {Marker("FilledSquare")}, Item ID("mixer", 1))
			)}
		),
		Dispatch({}, "400", LegendBox,
			{Legend Position({7, [0, 1, 2, 3, 4, -1, -1]})}
		)
	)
);

frame = Report(gb)[FrameBox(1)];
seg = (frame << FindSeg(Marker Seg(1)));
seg << Set Marker Draw Expr(
	Function({this seg, this row, x, y, size, row state},
		Fill Color(Color Of(Row State(this row)));
		Rect(x, y + 0.3, x + (:Stop[this row] - x) / 2 + 0.1, y - 0.3, 1)
	)
);

seg = (frame << FindSeg(Marker Seg(2)));
seg << Set Marker Draw Expr(
	Function({this seg, this row, x, y, size, row state},
		Fill Color(Color Of(Row State(this row)));
		Rect(x - (x - :Start[this row]) / 2 - 0.1, y + 0.3, x, y - 0.3, 1)
	)
);

There are also most likely options where you heavily modify your data to fit just graphing needs.

-Jarmo
hogi
Level XII


Re: How do I make start/stop bar charts?

wow, this is amazing!

Maybe remove the "/2" and draw 2 overlapping rectangles. Then the bars stays stable even if start or stop is close to the edge or even outside of the graph.

disappears.mp4
Video Player is loading.
Current Time 0:00
Duration 0:00
Loaded: 0%
Stream Type LIVE
Remaining Time 0:00
 
1x
    • Chapters
    • descriptions off, selected
    • captions off, selected
      (view in My Videos)

       

       

       

      jthi
      Super User


      Re: How do I make start/stop bar charts?

      There are basically infinite amount of ways of doing this. Pick which best suits for needs (or create your own). Rect from start to end while utilizing average point allows easily using start/stop markers for example while adding extra "marker" to center for user to click.

      jthi_0-1742037411705.png

      -Jarmo
      hogi
      Level XII


      Re: How do I make start/stop bar charts?

      Instead of 

      Color Of(Row State(this row))

      can Set Marker Draw Expr() also use the the color theme defined via the Color dropzone?

      Is there a built-in function which does something like

      w= current window() << get namespace;
      
      
      // get the script - and from there the first color
      gbscript = gb << get script;
      vars = Extract Expr( gbscript, Variables( Wild List() ) );
      w:colorCol = Try(
      	Arg( Extract Expr( vars, Color( Wild() ) ), 1 ),
      	Caption( "no color" );
      	stop;
      );
      
      // use the legend server to gt the gradient settings
      legend = gb << get legend server;
      
      items = {};
      For Each( {list}, legend << get legend items, Insert Into( items, list ) );
      
      gradient = Filter Each( {item}, items, item << get Type == "Gradient" );
      If( Not( N Items( gradient ) ),
      	Caption( "no gradient" );
      	Stop();
      );
      
      gradient = gradient[1];
      
      // parse the gradient settings to create my own color interpolation function
      settings = gradient << Get Gradient Settings;
      colorTheme = settings["Color Theme"];
      colors = If( Is List( colorTheme ),
      	colorTheme[3],
      	Get Color Theme Detail( colorTheme )[3]
      );
      colors = Matrix( Remove( colors, N Items( colors ) ) );
      xs = ((1 :: N Items( colors[0, 1] )) - 1) / (N Items( colors[0, 1] ) - 1);
      
      scale = settings["Scale Values"];
      reverse = settings["Reverse Gradient"];
      min = scale[If( reverse, 2, 1 )];
      max = scale[If( reverse, 1, 2 )];
      Eval(
      	Eval Expr(
      		w:col = Function( {x},
      			x2 = (x - Expr( min )) / (Expr( max - min ));
      			Eval List(
      				{Interpolate( x2, xs, Expr( colors[0, 1] ) ), Interpolate( x2, xs, Expr( colors[0, 2] ) ),
      				Interpolate( x2, xs, Expr( colors[0, 3] ) )}
      			);
      		)
      	)
      );  

       

       

       

       

       

       

       

       

       

      hogi
      Level XII


      Re: How do I make start/stop bar charts?

      It is interesting that "Size" is among the parameters which are transferred to 

      Set Marker Draw Expr

      and that Color is not.

      BHarris
      Level VI


      Re: How do I make start/stop bar charts?

      The JSL rect-drawing approach does create the correct image, and I'm thrilled to learn how it works in JMP.  I'll need to play with that more.

       

      What we lose, however, is the ability to click inside the bars to select the corresponding rows in the data table.  My dataset is also quite large (multi-million rows) and is divided into sets that are keyed by a 4th column that goes into the local filter.  This way we can look at any set of results quickly in the same window.  I know coding the JSL to update the bars whenever the Local Data Filter changes is possible, but it adds another layer of complexity.

       

      I think I'll submit a wish list item to fix/update the "Bar Overlap" setting to allow the "ID" column to collapse the different rows into a single one when used as an overlay.

       

      Impressive responses all around!  Thank you to all who have responded!