I am trying to get error bars on a 3D scatter plot I have. I have seen this topic on here 'Plotting columns of an list or array with scatter3D in python' However mine is an array of z values with a corresponding array of error values.
Here is the code
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits import mplot3d
df = pd. read_csv(r'C:\Users\brown\Dropbox\Thesis\8. Pharm Method development 5 - IDR zone\Excel docs\test.csv')
print (df)
#data
fx = (0.5,1.5,2,6)
fy = (25,20.5,16)
z = [37.8 38.61 42.29 43.8
32.47 33.34 38.39 39.19
24.68 26.32 28.49 30.58]
x, y = np.meshgrid(fx, fy)
#error data
zerror = [3.1 3.7 3.7 4.36
1.44 1.47 2.85 2.2
0.7 0.49 2.03 1.47]
#plot points
fig = plt.figure(figsize = (10,10))
ax = fig.gca(projection='3d')
surf=ax.scatter3D(x, y, z, c=z, cmap="jet", s=200, edgecolors="black", linewidth=1, marker= "^", antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.set_xlabel('Measurement zone area (mm²)')
ax.set_ylabel('Distance from compact (mm)')
ax.set_zlabel('IDR (µg/min/cm²)')
ax.set_title('Ibuprofen non-plate')
ax.view_init(30, 300)
plt.rcParams["axes.edgecolor"] = "yellow"
plt.rcParams["axes.linewidth"] = 2
#plot errorbars
for i in np.arange(0, len(fx)):
ax.plot([x[i], x[i]], [y[i], y[i]], [z[i] zerror[i], z[i]-zerror[i]], marker="_")
**Data frame values**
a a sd b b sd c c sd d d sd
0 37.80 3.10 38.61 3.70 42.29 3.70 43.80 4.36
1 32.47 1.44 33.34 1.47 38.39 2.85 39.19 2.20
2 24.68 0.70 26.32 0.49 28.49 2.03 30.58 1.47
I get a 3D scatter graph with all the points on, but no error bars.
I get the error message 'input operand has more dimensions than allowed by the axis remapping'
I would really appreciate any help,
Many thanks
CodePudding user response:
The issue was with formatting of your z
and zerror
variables (in your original code, you were wrapping the pandas operations in lists, so you need to remove the external brackets [ ]
from around them).
Once that is done, we can plot the lines by fixing the xy positions, and drawing a line from z zerror, z-zerror.
The snippet below does what you want:
import matplotlib.pyplot as plt
import numpy as np
# Move these here to set these values before plotting
plt.rcParams["axes.edgecolor"] = "yellow"
plt.rcParams["axes.linewidth"] = 2
#data
fx = (0.5,1.5,2,6)
fy = (25,20.5,16)
z = [[37.8, 38.61, 42.29, 43.8], # Pay attention to the formatting here!
[32.47, 33.34, 38.39, 39.19],
[24.68, 26.32, 28.49, 30.58]]
x, y = np.meshgrid(fx, fy)
#error data
zerror = [[3.1, 3.7, 3.7, 4.36], # Pay attention to the formatting here!
[1.44, 1.47, 2.85, 2.20],
[0.7, 0.49, 2.03, 1.47]]
#plot points
fig = plt.figure(figsize = (10,10))
ax = fig.gca(projection='3d')
surf=ax.scatter3D(x, y, z, c=z, cmap="jet", s=200, edgecolors="black", linewidth=1, marker= "^", antialiased=False)
fig.colorbar(surf, shrink=0.5, aspect=10)
ax.set_xlabel('Measurement zone area (mm²)')
ax.set_ylabel('Distance from compact (mm)')
ax.set_zlabel('IDR (µg/min/cm²)')
ax.set_title('Ibuprofen non-plate')
ax.view_init(30, 300)
#plot errorbars
for i in np.arange(0, len(fx)-1): # Lines were modified here!
for xval, yval, zval, zerr in zip(x[i], y[i], z[i], zerror[i]):
ax.plot([xval, xval], [yval, yval], [zval zerr, zval-zerr], marker="_", color='k')
plt.show()