基于频率调整pyplot.hexbin中六边形相对大小的方法咨询
Hey there! You’re spot on that matplotlib.pyplot.hexbin() doesn’t have a built-in parameter to make hexagon sizes proportional to their count/frequency—binsize only controls how the data is partitioned into bins, not the visual size of each hex. The approach you read about (size scaling with count) is totally doable, though; it just requires a little extra work to extract the bin data and plot it manually.
Here’s a step-by-step way to implement it:
1. Calculate Hexbin Bins First
First, run hexbin to compute the bin counts and their center coordinates. We won’t display the default hexbin plot, just use it to get the underlying data:
import matplotlib.pyplot as plt import numpy as np # Generate sample data (replace with your own dataset) np.random.seed(42) x = np.random.normal(0, 1, 1000) y = np.random.normal(0, 1, 1000) # Compute hexbin data without rendering the default plot hb = plt.hexbin(x, y, gridsize=20, visible=False) counts = hb.get_array() # Extract frequency/count for each bin centers = hb.get_offsets() # Get (x,y) center coordinates of each hex bin
2. Plot Scaled Hexagons with scatter
Use plt.scatter() with a hexagon marker (marker='h'), and set the s (size) parameter to scale with the counts array. Tweak the scaling factor to fit your plot’s dimensions:
# Define a scaling factor (adjust this based on your data range) size_scaler = 50 # Plot hexagons where size and color both map to frequency plt.scatter(centers[:, 0], centers[:, 1], s=counts * size_scaler, marker='h', c=counts, cmap='viridis', alpha=0.8) # Add colorbar for context plt.colorbar(label='Frequency') plt.xlabel('X') plt.ylabel('Y') plt.title('Hexagons Scaled by Frequency') plt.show()
3. Optional: Exact Hexagon Path Scaling
If you want hexagons that match the exact shape/orientation of hexbin (instead of the scatter marker), extract the path of a single hex and scale it based on counts. This is more verbose but gives perfect alignment:
from matplotlib.patches import PathPatch # Get the path template for one hexagon from the hexbin object hex_path = hb.get_paths()[0] fig, ax = plt.subplots() for center, count in zip(centers, counts): if count == 0: continue # Skip empty bins to clean up the plot # Scale the hex path based on count (adjust the scaling term as needed) scaled_path = hex_path.transformed( plt.matplotlib.transforms.Affine2D().scale(np.sqrt(count)/3) + plt.matplotlib.transforms.Affine2D().translate(*center) ) patch = PathPatch(scaled_path, color=plt.cm.viridis(count/max(counts)), alpha=0.8) ax.add_patch(patch) # Set plot limits to match the original hexbin extent ax.set_xlim(hb.get_extent()[0], hb.get_extent()[1]) ax.set_ylim(hb.get_extent()[2], hb.get_extent()[3]) plt.colorbar(plt.cm.ScalarMappable(norm=plt.Normalize(0, max(counts)), cmap='viridis'), label='Frequency') plt.xlabel('X') plt.ylabel('Y') plt.title('Exact Scaled Hexagons by Frequency') plt.show()
Key Notes
- Using
visible=Falseinhexbinprevents the default fixed-size hexes from cluttering your plot. - Using the square root of counts (in the path scaling example) helps avoid large bins overwhelming the plot—you can adjust this based on how dramatic you want the size difference to be.
- The "Multivariate Hexagonal Binning" approach you referenced relies on this exact logic: tying both the size and color of hexes to their count, which makes high-density areas far more prominent than fixed-size hexbin plots.
内容的提问来源于stack exchange,提问作者L. Robinson

