pythonmatplotlibmplot3dscatter3dmatplotlib-3d

Adding a colorbar by the dates of points in a 3D scatter plot


I am attempting to plot earthquakes of a certain region in a 3D plot with the color as a way to show time/date of the event. The data points are accurately colored, however, when I plot the color bar it only displays 0.0 to 1.0. How do I get the color bar to show the dates as its label?

My dates variable is a list of dates in "YYYY-MM-DD" format.

%matplotlib notebook
from mpl_toolkits.mplot3d import axes3d

fig = plt.figure(figsize=(8,8))
ax = fig.add_subplot(projection='3d')

ax.scatter(longitude, latitude, -depth, c=mdates.date2num(dates), cmap='magma')
fig.colorbar(mpl.cm.ScalarMappable(cmap='magma'))
plt.show()

Solution

  • Since you didn't provide the data, I had to randomly generate it.

    from mpl_toolkits.mplot3d import axes3d
    import matplotlib.dates as mdates
    import matplotlib.pyplot as plt
    import matplotlib as mpl
    from matplotlib.colors import Normalize
    import numpy as np
    
    # generate random data and dates
    longitude = np.random.uniform(0, 1, 100)
    latitude = np.random.uniform(0, 1, 100)
    depth = np.random.uniform(0, 1, 100)
    
    dates = []
    for i in range(1, 13):
        for j in range(1, 25):
            if j < 10: n = "0" + str(j)
            else: n = j
            if i < 10: m = "0" + str(i)
            else: n = i
            dates.append("2022-{}-{}".format(m, n))
    
    fig = plt.figure(figsize=(8,8))
    ax = fig.add_subplot(projection='3d')
    
    colors = mdates.date2num(dates[:100])
    ax.scatter(longitude, latitude, -depth, c=colors, cmap='magma')
    norm = Normalize(vmin=colors.min(), vmax=colors.max())
    
    # choose a proper number of ticks to be shown on the colorbar
    N = 5
    ticks = np.linspace(colors.min(), colors.max(), N)
    # convert the tick back to date format
    labels = [mdates.num2date(t).strftime("%Y-%m-%d") for t in ticks]
    cb = fig.colorbar(
        mpl.cm.ScalarMappable(norm=norm, cmap='magma'),
        ticks=ticks,
        ax=ax,
        label="Date"
    )
    cb.ax.set_yticklabels(labels)
    plt.show()
    

    enter image description here