如何在Pandas计时差统计图中添加跑步成绩标记或红色条形?
Got it, let's work through your two requests and fix that tricky timedelta marker issue you mentioned. The key here is making sure we're aligning your personal time with the grouped timedelta indices correctly, since Pandas stores Timedelta as nanosecond-resolution 64-bit integers which can cause mismatches if not handled properly.
Solution 1: Add Red Marker/Line to the Line Graph
First, let's adjust your existing code to add a clear red marker or vertical line for your personal time. We'll use matplotlib directly to get more control over the plot elements:
import pandas as pd import matplotlib.pyplot as plt # Your original data processing code df['new_time'] = pd.to_timedelta(df['time'], errors='coerce') time_frame = '5min' # Using '5min' is more readable than calculating 60*5 seconds lap_time = df.groupby(pd.Grouper(key='new_time', freq=time_frame)).count() # Initialize plot fig, ax = plt.subplots() lap_time['count'].plot(ax=ax, label='Finishers per 5min Interval') # Convert your personal time to the same Timedelta type personal_time = pd.to_timedelta("01:07:45") # Option 1: Add a vertical red dashed line ax.axvline(x=personal_time, color='red', linestyle='--', linewidth=2, label='Your Time') # Option 2: Add a red scatter marker at the exact group's count value # First find which interval your time falls into personal_interval = pd.cut([personal_time], bins=lap_time.index)[0] # Plot the marker on top of the line ax.scatter(personal_interval.mid, lap_time.loc[personal_interval, 'count'], color='red', s=120, zorder=5, edgecolor='black') # Add legend and labels ax.legend() ax.set_xlabel('Finish Time Intervals') ax.set_ylabel('Number of Runners') plt.title('Finish Time Distribution with Your Result Highlighted') plt.show()
This fixes the marker issue by ensuring your personal time is converted to the same Timedelta type as the grouped indices, and using pd.cut to precisely map it to the correct 5-minute interval.
Solution 2: Convert to Bar Chart with Highlighted Group
For the bar chart, we'll dynamically set the color of the bar corresponding to your personal time to red, while keeping others the default color. Here's how:
import pandas as pd import matplotlib.pyplot as plt # Data processing (same as before) df['new_time'] = pd.to_timedelta(df['time'], errors='coerce') time_frame = '5min' # Drop empty intervals to clean up the chart lap_time = df.groupby(pd.Grouper(key='new_time', freq=time_frame)).count().dropna(subset=['count']) # Convert personal time and find its group index personal_time = pd.to_timedelta("01:07:45") # Use get_indexer to find the nearest interval (handles nanosecond precision) personal_group_idx = lap_time.index.get_indexer([personal_time], method='nearest')[0] # Create color list: default to blue, set your group to red bar_colors = ['#1f77b4'] * len(lap_time) bar_colors[personal_group_idx] = '#ff4b5c' # Plot the bar chart lap_time['count'].plot(kind='bar', color=bar_colors, figsize=(10,6)) # Add a text label above your bar for clarity plt.text(personal_group_idx, lap_time.iloc[personal_group_idx]['count'] + 1, 'Your Time', ha='center', va='bottom', color='#ff4b5c', fontweight='bold') # Format the plot plt.xlabel('5-Minute Finish Time Intervals') plt.ylabel('Number of Finishers') plt.title('Finish Time Distribution (Bar Chart)') plt.xticks(rotation=45, ha='right') plt.tight_layout() plt.show()
The get_indexer method here is crucial—it handles the nanosecond precision mismatch by finding the closest interval to your personal time, ensuring we highlight the correct bar every time.
内容的提问来源于stack exchange,提问作者pinq-

