如何在Pandas中实现groupby分组内排序并保留聚合结果,同时按store实现facet分面可视化?
Got it, let's break down how to build those store-specific facet plots with your already aggregated and sorted data. First, we need to tweak the data structure a bit since your df_2 has multi-level columns/indexes, which can throw off plotting libraries.
Step 1: Clean Up the Data Format
First, let's flatten that multi-level column and convert the index into regular columns—this makes plotting way easier:
# Flatten the multi-level column name ('sales', 'sum') to a simple 'sales_sum' df_2.columns = ['sales_sum'] # Turn the multi-level index into regular columns df_plot = df_2.reset_index()
Step 2: Use Seaborn FacetGrid for Easy Faceting
Seaborn's FacetGrid is perfect for this kind of per-group visualization. It'll automatically create a subplot for each store, and we can keep your pre-sorted sales order intact:
import seaborn as sns import matplotlib.pyplot as plt # Set a clean plot style sns.set_style("whitegrid") # Create the facet grid—one subplot per store, stacked vertically g = sns.FacetGrid(df_plot, col="store", col_wrap=1, height=4, aspect=2) # Map a barplot to each subplot, using our pre-sorted data g.map(sns.barplot, "product", "sales_sum") # Add labels and titles to make it readable g.set_axis_labels("Product", "Total Sales") g.set_titles("Store: {col_name}") # Adjust layout so nothing gets cut off plt.tight_layout() plt.show()
Pro Tip: Enforce Group-Specific Sorting
If you want to make 100% sure each store's products are sorted by sales descending (in case the global product order doesn't match each store's local order), use map_dataframe with a custom plotting function:
g = sns.FacetGrid(df_plot, col="store", col_wrap=1, height=4, aspect=2) def plot_sorted_bars(data, **kwargs): # Sort the store's data again (just to be safe) sorted_data = data.sort_values('sales_sum', ascending=False) sns.barplot(x="product", y="sales_sum", data=sorted_data, **kwargs) g.map_dataframe(plot_sorted_bars) # Add labels/titles as before g.set_axis_labels("Product", "Total Sales") g.set_titles("Store: {col_name}") plt.tight_layout() plt.show()
Alternative: Manual Plotting with Matplotlib
If you prefer full control with Matplotlib, you can loop through each store and create subplots manually:
stores = df_plot['store'].unique() # Create a grid of subplots—one row per store fig, axes = plt.subplots(nrows=len(stores), ncols=1, figsize=(10, 4*len(stores))) for ax, store in zip(axes, stores): # Grab data for the current store and sort it store_data = df_plot[df_plot['store'] == store].sort_values('sales_sum', ascending=False) # Plot the bar chart ax.bar(store_data['product'], store_data['sales_sum']) # Add titles and labels ax.set_title(f"Store: {store}") ax.set_xlabel("Product") ax.set_ylabel("Total Sales") plt.tight_layout() plt.show()
Either approach will give you the facet plots you're looking for—each store gets its own subplot showing total sales per product, sorted from highest to lowest.
内容的提问来源于stack exchange,提问作者Napier

