Black Lives Matter. Please consider donating to Black Girls Code today.

How to control surface plot axis ordering?

I am attempting to use the ‘surfaceplot’ type to display the geometry of a geological surface within a map region where the x, y, and z coordinates are in meters. While x and y in the data that I’m working with are ordered as you would expect (values should increase to the east for x and to the north for y) for z larger values mean greater depths. Unfortunately when using the ‘surface’ plot type, however, I have failed to get the z axis values to be ordered in the desired directions.

I have attempted the following things but none of them have helped me to get the axis ordering I’m after:

  • Set the ‘range’ attribute under scene.zaxis. When the the first number in the range is the smaller value things work fine irrespective of the absolute values that are used (for instance the plot renders correctly when modifying the example below to scene.zaxis.range: [-2, 8] even though the data range is 1 to 5) . However, when you put the larger value first to reverse the order (this works nicely in the ‘scatter’ plot type for instance), the plot axes are rendered but the surface is not.

  • Set the scene.categoryorder to any of the listed options (e.g., ‘trace’, ‘category ascending’, ‘category descending’, or ‘array’). As an example setting scene.categoryorder: ‘category ascending’ and scene.categoryarray: z has no apparent influence on how the plot is rendered, nor does using scene.categoryorder: ‘category descending’ and scene.categoryarray: z. Omitting the scene.categoryarray attribute while still setting scene.categoryorder has no effect either.

Thanks in advance to anyone who can come to my rescue!

Here is the JavaScript code for the plot above:

3D Surface Example 0
<body>
	<div id='myDiv'></div>
	<script>

	var x = [1, 2, 3, 4, 5];
	var y = [1, 2, 3, 4, 5, 6];
	var z = [
		[5, 5, 5, 5, 5], 
		[5, 4, 4, 4, 4], 
		[5, 4, 3, 3, 3], 
		[5, 4, 3, 2, 2], 
		[5, 4, 3, 2, 1], 
		[5, 4, 3, 2, 1]];
	var trace1 = {
		x: x,
		y: y,
		z: z,
		type: 'surface',
	};

	var data = [trace1];

	var layout = {
		width: 700,
		height: 700,
		hoverinfo: 'all',
		scene: {
			xaxis: {range: [1, 5]},
			yaxis: {range: [1, 6]},
			zaxis: {range: [1, 5], categoryorder: 'descending', categoryarray: z}
		},
	};

	Plotly.newPlot('myDiv', data, layout);

	</script>
</body>

categoryorder has only an effect for (you guessed it) categorical axes. Your graph has numerical values; hence, this attribute has no effect.

Hmm. That should work. Maybe we haven’t implemented reversed axes in 3D yet. Let me check,


In the meantime, I recommend manually reversing your x and y and z data arrays to get the desired result.

Thanks for your reply @etienne. I can’t see how I can reorder the z values given that they need to be in a 2D array. What I can do though is to make the values negative. That isn’t ideal but at least gets the right geometry.