1

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

  • As is, we cannot test your code without access to your csv file. Can you edit your question and replace the values obtained from the dataframe with values (declared inside the code) that reproduce your issue? – jfaccioni Sep 16 '21 at 14:12
  • Hi yes of course, I have pasted them at the bottom as a dataframe and also put them in the main body of code. – Benedict Brown Sep 16 '21 at 14:44

1 Answers1

2

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()

output image:enter image description here

jfaccioni
  • 7,099
  • 1
  • 9
  • 25