Search code examples
pythonmultidimensional-arraybinning

bin 3d points into 3d bins in python


How can I bin 3d points into 3d bins? Is there a multi dimensional version for np.digitize? I can use np.digitize separately for each dimension, like here. Is there a better solution? Thanks!


Solution

  • You can do this with numpy.histogramdd(sample), where the number of bins in each direction and the physical range can be adjusted as with a 1D histogram. More info on the reference page. For more general statistics, like the mean of another variable per point in a bin, you can use the scipy scipy.stats.binned_statistic_dd function, see docs. For your case with an array of three dimensional points, you would use this in the following way,

    import numpy as np
    from mpl_toolkits.mplot3d import Axes3D
    import matplotlib.pyplot as plt
    from scipy import stats
    
    
    #Setup some dummy data
    points = np.random.randn(1000,3)
    hist, binedges = np.histogramdd(points, normed=False)
    
    #Setup a 3D figure and plot points as well as a series of slices
    fig = plt.figure()
    ax1 = fig.add_subplot(111, projection='3d')
    ax1.plot(points[:,0],points[:,1],points[:,2],'k.',alpha=0.3)
    
    #Use one less than bin edges to give rough bin location
    X, Y = np.meshgrid(binedges[0][:-1],binedges[1][:-1])
    
    #Loop over range of slice locations (default histogram uses 10 bins)
    for ct in [0,2,5,7,9]: 
        cs = ax1.contourf(X,Y,hist[:,:,ct], 
                          zdir='z', 
                          offset=binedges[2][ct], 
                          level=100, 
                          cmap=plt.cm.RdYlBu_r, 
                          alpha=0.5)
    
    ax1.set_xlim(-3, 3)
    ax1.set_ylim(-3, 3)
    ax1.set_zlim(-3, 3)
    plt.colorbar(cs)
    plt.show()
    

    which gives a series of histogram slices of occupancy at each location,

    enter image description here