如何在Seaborn FacetGrid绘制热力图时访问行列信息并添加填充图案
Solution to Add Hatch Patterns to Seaborn FacetGrid Heatmaps
To add conditional hatch patterns to each heatmap in your FacetGrid—based on the facet's row/column values (a and b) and cell values—you need to access the current facet's metadata inside your heatmap drawing function. Here's how to do it:
Key Steps Explained
- Access the Current Facet's Axes: When using
map_dataframe, Seaborn automatically passes the current axis (ax) to your drawing function as a keyword argument. - Retrieve Facet's a/b Values: Use the FacetGrid's
axes_dict(a map of (row_value, col_value) to axis objects) to find which (a, b) pair corresponds to the current axis. - Compute Hatch Mask: Apply your custom function (
myFunc) to each cell in the heatmap data, using the current a/b values and cell-specific data. - Overlay Hatch Pattern: Use
ax.pcolorto draw the hatch pattern on top of the heatmap, using a masked array to target only the cells that need hatching.
Full Working Code
import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # Custom function to determine if a cell gets a hatch pattern def myFunc(fgA, fgB, d_val, c_val, cell_val): # Example logic: Apply hatch if sum of a + b >15 AND cell value >2 # Adjust this logic to match your specific requirements return 5 if (fgA + fgB) > 15 and cell_val > 2 else 0 # Create your sample data d = np.array(np.meshgrid(np.arange(1,6), np.arange(6,11), np.arange(1,6), np.arange(6,11))).T.reshape(-1,4) d = np.c_[d, np.random.randint(1,5,625)] df = pd.DataFrame(d, columns=['a','b','c','d','e']) # Initialize the FacetGrid fg = sns.FacetGrid(df, col='b', row='a', margin_titles=True, height=5, aspect=1) # Define the heatmap drawing function with hatch logic def draw_heatmap(x_col, y_col, val_col, **kwargs): # Get the current axis for this facet ax = kwargs.pop('ax') # Get the subset of data assigned to this facet data = kwargs.pop('data') # Pivot and sort data to form the heatmap matrix heatmap_data = data.pivot(index=y_col, columns=x_col, values=val_col) heatmap_data = heatmap_data.sort_index(ascending=False) # Find the current a and b values for this facet for (a_val, b_val), facet_ax in fg.axes_dict.items(): if facet_ax is ax: current_a = a_val current_b = b_val break # Calculate which cells need hatching using your custom function hatch_mask = heatmap_data.stack().apply( lambda cell: myFunc(current_a, current_b, cell.name[0], cell.name[1], cell) ).unstack() # Create a masked array: only values >=5 will show the hatch masked_hatch = np.ma.masked_less(hatch_mask.values, 5)[::-1] # Reverse to align with heatmap's y-axis # Draw the base heatmap sns.heatmap(heatmap_data, ax=ax, **kwargs) # Overlay the hatch pattern (alpha=0 keeps fill transparent) x_coords = np.arange(len(heatmap_data.columns) + 1) y_coords = np.arange(len(heatmap_data.index) + 1) ax.pcolor(x_coords, y_coords, masked_hatch, hatch='//', alpha=0.) # Apply the function to all facets in the grid fg = fg.map_dataframe(draw_heatmap, 'c', 'd', 'e', cbar=False, cmap='viridis', annot=True, fmt=".0f", linewidths=.5) # Adjust layout and display the plot plt.tight_layout() plt.show()
Important Notes
- Customize
myFunc: Modify the logic insidemyFuncto match your specific criteria for applying hatch patterns. The function should return a value >=5 when you want a hatch (since we usenp.ma.masked_lessto mask values below 5). - Axis Alignment: We reverse the
masked_hatcharray with[::-1]to match the heatmap's reversed y-axis (where the first row of data appears at the top of the plot). - Hatch Style: Change the
hatchparameter inax.pcolorto use different patterns (e.g.,'\\\\','x','+','.').
内容的提问来源于stack exchange,提问作者insofern
相关产品推荐
相关产品推荐

