基于跑步赛事数据集分组创建多组水平条形图:for loop与groupby的选择咨询
Great question! Since your age groups are dynamic (they shift based on each race's dataset), you’ll need a combination of groupby() and a for loop to make this work. Here’s a step-by-step breakdown with code to implement exactly what you want:
Step 1: Understand the Approach
You can’t rely on just groupby() alone here—groupby() will organize your data into chunks by age group, but since the number of groups is dynamic, a for loop is necessary to iterate over each chunk and generate a separate bar plot for one. This combination lets you handle any number of age groups automatically, no matter how the dataset changes.
Step 2: Code Implementation (Using Matplotlib)
First, let’s set up the example data and then build the plots:
import pandas as pd import matplotlib.pyplot as plt # Example dataset (matches your sample) data = { 'Name': ['John', 'Mike', 'Travis', 'James'], 'Age Group': ['30-39', '30-39', '40-49', '40-49'], 'Finish Time': [15.5, 17.2, 20.4, 22.1], 'Finish Place': [1, 2, 1, 2], 'Hometown': ['New York City', 'Denver', 'Louisville', 'New York City'], 'Times Ran The Race': [2, 1, 3, 1] } df = pd.DataFrame(data) # Group data by Age Group age_groups = df.groupby('Age Group') # Loop through each age group to create a separate plot for group_name, group_data in age_groups: # Sort the group by Finish Time (fastest first), then reverse to put fastest at the bottom sorted_runners = group_data.sort_values('Finish Time', ascending=True).iloc[::-1] # Create a new figure for this age group plt.figure(figsize=(10, len(sorted_runners)*0.8)) # Draw horizontal bar plot bars = plt.barh(sorted_runners['Name'], sorted_runners['Finish Time'], color='lightcoral') # Add Hometown and Race Count labels next to each bar for idx, bar in enumerate(bars): runner_info = sorted_runners.iloc[idx] # Position text to the right of the bar, centered vertically plt.text( bar.get_width() + 0.3, bar.get_y() + bar.get_height()/2, f"{runner_info['Hometown']} | Ran {runner_info['Times Ran The Race']}x", va='center', fontsize=10 ) # Customize plot appearance plt.title(f"Race Results: {group_name} Age Group", fontsize=14, pad=15) plt.xlabel("Finish Time (Minutes)", fontsize=12) plt.ylabel("Runner Name", fontsize=12) plt.xlim(0, sorted_runners['Finish Time'].max() + 4) # Add padding for labels plt.tight_layout() # Show the plot (or use plt.savefig() to save as files) plt.show()
Key Details Explained
- Sorting & Reversing: We sort each group by
Finish Timein ascending order (fastest first), then reverse the dataframe so the fastest runner appears at the bottom of the horizontal bar plot (since matplotlib’sbarh()draws from top to bottom by default). - Dynamic Figure Size: The figure height adjusts based on the number of runners in each age group, so plots don’t look cramped for larger groups.
- Labeling: We add the hometown and race count as text next to each bar for clarity—you could also adjust this to place the text below the runner names if preferred (just tweak the
plt.text()coordinates).
Alternative: Seaborn for Grid Layout
If you prefer all plots in a single grid instead of separate figures, you could use seaborn.catplot() with row='Age Group', but this won’t give you completely independent figures. The loop approach is better if you need each age group’s plot as a standalone file/window.
内容的提问来源于stack exchange,提问作者DomCobb

