Search code examples
pythonmatplotlibplot

Machine Learning Visualization Scatterplot


I am striving to reproduce the visualization style in the provided image. It looks like a scatterplot is used to show the data points. When I attempt to create a similar visualization, all the locations become visible. My objective is to create the other scatterplot, featuring larger circles that exhibit a darker shade of red in areas with more activity and a lighter shade where activity is less pronounced.

I believe I need to implement a threshold to selectively display data points and avoid showing all of them. Can anyone provide guidance on how I can achieve a visualization similar to the one depicted in the picture?

My plot:

enter image description here

The plot i want:

ScatterPlot i want

My code:


def plot_cumulative_heatmap(positions: List[Tuple[float, float]], map_name: str = "de_mirage", map_type: str = "original", dark: bool = False, titel: str = "Counter-Terrorist Attacking", isPistol: str = "Pistol Round") -> Literal[True]:
    heatmap_fig, heatmap_axes = plot_map(map_name=map_name, map_type=map_type, dark=dark)
    
    heatmap_data = []

    for position in positions:
        x, y = position
        heatmap_data.append((x, y))

    # Extract data for plotting
    x, y = zip(*heatmap_data)

    sns.scatterplot(x=x, y=y, color='red', s=5, ax=heatmap_axes, alpha=0.5)
    heatmap_axes.set_title(f"{titel}\nTotal Positions: {len(positions)}\n{isPistol}", fontsize=14, weight="bold")
    heatmap_axes.get_xaxis().set_visible(False)
    heatmap_axes.get_yaxis().set_visible(False)

    print("Heatmap saved.")
    return True

Solution

  • One transparent circle per input point

    The following approach draws large transparent circles for each input coordinate pair. If the real input contains multiple points with the same coordinates, their transparency will add up.

    import matplotlib.pyplot as plt
    import numpy as np
    
    # create some dummy test data
    np.random.seed(20240311)
    x = np.random.randn(20, 25).cumsum(axis=1).ravel()
    y = np.random.randn(20, 25).cumsum(axis=1).ravel()
    filter = (np.abs(x) < 7) & (np.abs(y) < 7) & ((np.abs(x) > 5) | (np.abs(y) > 5))
    x = x[filter]
    y = y[filter]
    
    fig, ax = plt.subplots()
    fig.set_facecolor('black')
    ax.set_aspect('equal', 'datalim')
    ax.scatter(x, y, color='salmon', alpha=0.3, lw=0, s=500)
    
    # draw rectangles representing the walls
    ax.add_patch(plt.Rectangle((-7, -7), 14, 14, fc='none', ec='w', lw=2))
    ax.add_patch(plt.Rectangle((-5, -5), 10, 10, fc='none', ec='w', lw=2))
    ax.axis('off')
    
    plt.show()
    

    drawing transparent circles for scatter dots

    Use KMeans to group together points, alpha depending on count

    Another approach uses KMeans to find the centers of groups of points that are close together. Then, large dots can be drawn at those places, with transparency depending on the number of points in each cluster.

    Change the number of clusters (here n_clusters=20) to get more or less circles.

    from sklearn.cluster import KMeans
    import matplotlib.pyplot as plt
    import numpy as np
    
    # dummy test data from the other example
    
    kmeans = KMeans(n_clusters=20, init='k-means++', random_state=0)
    kmeans.fit(np.c_[x, y])
    
    centroids = kmeans.cluster_centers_
    labels = kmeans.labels_
    counts = np.bincount(labels)
    max_count = counts.max()
    
    fig, ax = plt.subplots()
    fig.set_facecolor('black')
    ax.set_facecolor('none')
    alphas = 0.2 + 0.8 * counts / max_count
    ax.scatter(x=centroids[:, 0], y=centroids[:, 1], color='salmon', s=1000, lw=0, alpha=alphas)
    ax.set_aspect('equal', 'datalim')
    
    # draw rectangles representing the walls
    ax.add_patch(plt.Rectangle((-7, -7), 14, 14, fc='none', ec='w', lw=2, zorder=0))
    ax.add_patch(plt.Rectangle((-5, -5), 10, 10, fc='none', ec='w', lw=2, zorder=0))
    ax. Axis('off')
    plt.tight_layout()
    plt.show()
    

    KMeans to find cluster centers, alpha via count