如何用Python实现 Census 数据的雷达图网格(Facet Grid of Radar/Spider Plots)绘制?
Let’s dive right in—yes, this is totally feasible in Python, and with a few targeted tweaks to your current approach, you’ll get that facet grid of radar plots set up exactly how you need it for your census data analysis. Here’s a breakdown of the key points you might be missing, plus an updated implementation tailored to your core goal:
Key Things to Adjust in Your Current Approach
- Optimize Your Data Structure: Your dataframe likely needs restructuring to make faceting easier. Aim for a format where each row combines a census year, a household head context, and the distribution values for kin contexts. If your data is in long format (one row per kin context), pivot it to wide format first so each year+household combo has one row with kin contexts as columns.
- Generalize Your Spider Plot Function: Stop tying the function to row indices—instead, make it accept a specific data subset and a pre-created axis. This lets you seamlessly plug it into a grid of subplots.
- Control Layout Explicitly: Use matplotlib’s
subplotsto build a grid where rows represent household contexts and columns represent census years (or vice versa, based on your preference). Polar subplots work perfectly here for radar charts. - Enforce Consistency: Lock in shared axis limits, angle offsets, and labels across all plots so your radar charts are directly comparable at a glance.
Updated Python Implementation
First, let’s assume your cleaned data (after pivoting if needed) looks like this (adjust column names to match your Context.xlsx):
| year | household_context | kin_urban | kin_rural | kin_institutional | ... |
|---|---|---|---|---|---|
| 1891 | Urban | 18 | 22 | 10 | ... |
| 1891 | Rural | 12 | 30 | 8 | ... |
| 1901 | Urban | 20 | 19 | 11 | ... |
Here’s the code to generate your desired facet grid:
import pandas as pd import matplotlib.pyplot as plt from math import pi # Load and prepare data df = pd.read_excel('Context.xlsx', header=0, engine='openpyxl') # Define unique groups for the facet grid years = df['year'].unique() household_contexts = df['household_context'].unique() n_years = len(years) n_contexts = len(household_contexts) # --- Generalized Radar Plot Function --- def make_spider(ax, data_subset, plot_title, color): # Extract kin context categories (exclude year and household context columns) kin_categories = [col for col in data_subset.columns if col not in ['year', 'household_context']] n_categories = len(kin_categories) # Calculate angles for the radar plot (close the loop) angles = [n / float(n_categories) * 2 * pi for n in range(n_categories)] angles += angles[:1] # Configure polar axis settings ax.set_theta_offset(pi / 2) ax.set_theta_direction(-1) # Add category labels to the axes ax.set_xticks(angles[:-1]) ax.set_xticklabels(kin_categories, color='grey', size=8) # Add radial scale labels and limits ax.set_rlabel_position(0) ax.set_yticks([10, 20, 30]) ax.set_yticklabels(["10", "20", "30"], color="grey", size=7) ax.set_ylim(0, 40) # Plot the radar data values = data_subset[kin_categories].values.flatten().tolist() values += values[:1] # Close the plot shape ax.plot(angles, values, color=color, linewidth=2, linestyle='solid') ax.fill(angles, values, color=color, alpha=0.4) # Add plot title ax.set_title(plot_title, size=11, color=color, y=1.1) # --- Build the Facet Grid --- # Set figure size (adjust based on number of plots) fig, axes = plt.subplots( nrows=n_contexts, ncols=n_years, figsize=(4*n_years, 3*n_contexts), subplot_kw={'polar': True} ) # Use a consistent color palette palette = plt.cm.get_cmap("Set2", n_contexts * n_years) color_counter = 0 # Loop through each household context (rows) and year (columns) for row_idx, context in enumerate(household_contexts): for col_idx, year in enumerate(years): # Get the specific data subset for this year+context combo subset = df[(df['year'] == year) & (df['household_context'] == context)] # Handle empty subsets (hide unused plots) if subset.empty: ax = axes[row_idx][col_idx] if n_contexts >1 and n_years>1 else (axes[row_idx] if n_years==1 else axes[col_idx]) ax.set_visible(False) continue # Grab the correct axis (handle single row/column edge cases) ax = axes[row_idx][col_idx] if n_contexts >1 and n_years>1 else (axes[row_idx] if n_years==1 else axes[col_idx]) # Generate the radar plot plot_title = f"{year} | Household: {context}" make_spider(ax, subset, plot_title, palette(color_counter)) color_counter +=1 # Adjust spacing to prevent label overlap plt.tight_layout() plt.show()
Quick Notes on the Code
- Flexible Function:
make_spidernow works with any data subset and pre-made axis, making it easy to scale to a grid. - Exact Layout: The grid uses rows for household contexts and columns for years—exactly the structure you wanted to replace your manual Excel workflow.
- Robustness: The code handles empty data subsets by hiding unused plots, so your grid stays clean even if some year+context combinations have no data.
Pro Tips for Debugging & Tweaks
- Test Small First: Start by plotting a single radar plot with one year+context subset to confirm your data is structured correctly before building the full grid.
- Clean Your Data: If you have missing values in your kin context columns, fill them with 0 to avoid broken radar plots.
- Style Adjustments: Tweak
figsize, label sizes, or the color palette (Set2can be swapped forviridis,tab10, etc.) to match your presentation needs.
内容的提问来源于stack exchange,提问作者Jean-Seb




