pythonstringlistplotscatter3d

3D Scatterplot in Python using strings instead of values


I need to make a 3d plot, where the axes will have labels in string instead of values. So I have 3 lists, the same size, and I need to have the first element of the first list to be my X coordinate, the first element of the second list to be my Y coordinate, and the first element of the third list to be my Z coordinate.

Here is my code:

x = ['7th generation', '7th generation', '7th generation', '7th generation', '7th generation', 'Dawn Ultra', 'Dawn Ultra', 'Dawn Ultra', 'Dawn Ultra', 'Dawn Ultra', 'Mrs Meyers', 'Mrs Meyers', 'Mrs Meyers', 'Mrs Meyers', 'Mrs Meyers', 'Ultra Palmolive', 'Ultra Palmolive', 'Ultra Palmolive', 'Ultra Palmolive', 'Ultra Palmolive']
y = ['0.05 ml : 25 ml', '0.05 ml : 25 ml', '0.05 ml : 25 ml', '0.05 ml : 25 ml', '0.05 ml : 37.5 ml', '0.05 ml : 37.5 ml', '0.05 ml : 37.5 ml', '0.05 ml : 37.5 ml', '0.05 ml : 50 ml', '0.05 ml : 50 ml', '0.05 ml : 50 ml', '0.05 ml : 50 ml', '0.05 ml : 62.5 ml', '0.05 ml : 62.5 ml', '0.05 ml : 62.5 ml', '0.05 ml : 62.5 ml', '0.05 ml : 75 ml', '0.05 ml : 75 ml', '0.05 ml : 75 ml', '0.05 ml : 75 ml']
z = [0, 0, 0, 0, 0, 0, 3, 0, 0, 1, 1, 0, 0, 4, 1, 0, 0, 0, 1, 6]

%matplotlib notebook 
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(x, y, z, c=y)
ax.set_xlabel("$detergent$")
ax.set_ylabel("$concentration$")
ax.set_zlabel("$num_colon$");

But it returns to me an error: ValueError: could not convert string to float: '7th generation'


Solution

  • The error is given since you are trying to plot a string in a numeric plot. You need to handle the conversion before. An option is to use a LabelEncoder by scikitlearn.

    from sklearn.preprocessing import LabelEncoder
    
    x_le = LabelEncoder()
    y_le = LabelEncoder()
    x_num = x_le.fit_transform(x)
    y_num = y_le.fit_transform(y)
    

    Then you can plot the values and set the original arrays as labels

    from mpl_toolkits.mplot3d import Axes3D
    fig = plt.figure() 
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(x_num, y_num, z, c=y_num)
    
    ax.set_xticks(range(0,len(x_le.classes_)))
    ax.set_xticklabels(x_le.classes_)
    
    ax.set_yticks(range(0,len(y_le.classes_)))
    ax.set_yticklabels(y_le.classes_)