基于Matplotlib绘制权重填充阶梯图——含权重历史DataFrame数据
Got it, let's build that filled step plot for your weight DataFrame. Since each weight value stays fixed until the next update date, we need to make sure the plot correctly captures that "hold" behavior, then add the filled areas for clarity.
Step 1: Prepare the Data
First, we need to extend our date and weight data to define the full duration each weight is active. Each weight starts on its set date and stays in effect until the next update date (we'll add a final date after the last entry to close out the last step).
Here's the code to handle this:
import pandas as pd import matplotlib.pyplot as plt # Assume your DataFrame is named weight_df (replace with your actual variable name) # Convert index to datetime if it's not already weight_df.index = pd.to_datetime(weight_df.index) # Create extended date list: each date + the next date (to mark the end of the weight period) extended_dates = [] for idx in range(len(weight_df.index)): extended_dates.append(weight_df.index[idx]) # Add the next date as the end of the current weight period (except for the last entry) if idx < len(weight_df.index) - 1: extended_dates.append(weight_df.index[idx + 1]) # Add a final date 1 day after the last entry to complete the last step extended_dates.append(weight_df.index[-1] + pd.Timedelta(days=1)) # Create extended weight values for each item (repeat each weight twice, then remove the last duplicate) extended_weights = {} for col in weight_df.columns: weight_vals = [] for val in weight_df[col]: weight_vals.extend([val, val]) # Trim the last duplicate to match the length of extended_dates weight_vals.pop() extended_weights[col] = weight_vals
Step 2: Plot Stacked Filled Step Chart
Since your weights sum to 1, a stacked plot lets you see how each item's share changes over time, with the total filling the full 0-1 range.
plt.figure(figsize=(12, 6)) # Track cumulative weight for stacking fills cumulative_weight = [0] * len(extended_dates) for item, weights in extended_weights.items(): # Draw the step line (where='pre' ensures the weight updates immediately on the set date) plt.step(extended_dates, weights, where='pre', label=item, linewidth=2) # Fill the area between the cumulative base and the current item's weight plt.fill_between( extended_dates, cumulative_weight, [base + w for base, w in zip(cumulative_weight, weights)], alpha=0.3 ) # Update cumulative weight for the next item cumulative_weight = [base + w for base, w in zip(cumulative_weight, weights)] # Format the plot plt.title('Item Weight History (Stacked Filled Step Plot)', fontsize=14) plt.xlabel('Date', fontsize=12) plt.ylabel('Weight', fontsize=12) plt.legend(title='Items', bbox_to_anchor=(1.05, 1), loc='upper left') plt.xticks(rotation=45) plt.tight_layout() plt.show()
Step 3: Alternative: Individual Filled Step Plots
If you prefer to view each item's weight change separately, use subplots:
fig, axes = plt.subplots(nrows=len(weight_df.columns), figsize=(12, 10), sharex=True) for ax, (item, weights) in zip(axes, extended_weights.items()): ax.step(extended_dates, weights, where='pre', color='#1f77b4', linewidth=2) ax.fill_between(extended_dates, 0, weights, alpha=0.3, color='#1f77b4') ax.set_title(f'Weight Trend for {item}', fontsize=12) ax.set_ylabel('Weight', fontsize=10) ax.set_ylim(0, 1) # Format the bottom subplot axes[-1].set_xlabel('Date', fontsize=12) axes[-1].tick_params(axis='x', rotation=45) plt.tight_layout() plt.show()
Key Notes
- The
where='pre'argument inplt.step()is critical: it tells Matplotlib to apply the new weight immediately on the set date, which matches your data's behavior (weights stay constant until the next update). - Extending the dates and weights ensures each weight's active period is clearly represented in the step plot.
内容的提问来源于stack exchange,提问作者jerickson759

