Search code examples
pythonmatplotlibscatter3dmatplotlib-3d

Plot 3D scatter plot from 3D array


I am currently trying to plot a 3D scatter plot by using a 3D array. What I found online about plotting 3D scatter plot looks something like ax.scatter3D(x, y, z) where x, y , z are all 1D array. However, in my case, I am generating an array of shapes(3, 3, 3) by using numpy's histogramdd.

In [61]: h, edges = histogramdd(array([[1,2,4],[4,2,8],[3,2,1],[2,1,2],[2,1,3],[2,1,1],[2,1,4]]),bins=3)
In [64]: h
Out[64]:
array([[[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  1.,  0.]],

       [[ 3.,  1.,  0.],
        [ 0.,  0.,  0.],
        [ 0.,  0.,  0.]],

       [[ 0.,  0.,  0.],
        [ 0.,  0.,  0.],
        [ 1.,  0.,  1.]]])

My question is, how can I unpack this (3, 3, 3) into 1-dimensional arrays that correspond to the axes so that I can plot 3d scatter plot?


Solution

  • I would say you need 4 dimensions to plot the histogram you have created. One idea could be using a 3D scatter plot changing the size of the marker to encode the information about the number of data points contained in each of the 3D bins.

    Here's what I would do.

    1. generate the 3D histogram
    import numpy as np
    
    a = np.array([[1,2,4],[4,2,8],[3,2,1],[2,1,2],[2,1,3],[2,1,1],[2,1,4]])
    h, edges = np.histogramdd(a, bins=3)
    
    1. Create the 3D coordinates of your bins position
    ex, ey, ez = edges
    x, y, z = np.meshgrid(np.linspace(ex[0], ex[-1], 3),
                          np.linspace(ey[0], ey[-1], 3),
                          np.linspace(ez[0], ez[-1], 3))
    
    1. Use a 3D scatter to plot your bin and change the size of the markers to encode the number of points contained in each plotted bin:
    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    
    ax.scatter(x.flatten(), y.flatten(), z.flatten(), s=h.flatten()*50)
    

    Here's the plot result:

    3D scatter plot