matplotlib bar()与pandas bar()的差异及两类柱状图绘图技术疑问
Great question! Let’s break this down into clear parts—first the key differences between matplotlib's bar() and pandas' plot.bar(), then solutions to your two specific issues.
matplotlib.pyplot.bar() and pandas.DataFrame.plot.bar() At their core, these two functions are related but serve different needs:
- Underlying Dependency: Pandas'
plot.bar()is a wrapper around matplotlib'sbar()function. Pandas simplifies plotting for its own data structures (DataFrames/Series) by handling data preparation (like grouping, indexing) automatically. Matplotlib'sbar()is a lower-level tool that requires you to manually define every piece of data (x positions, bar heights, labels) but gives you full control over every detail of the plot. - Use Case Fit: If you’re working directly with pandas data (like grouped Series),
pandas.plot.bar()is a one-line shortcut that saves you from writing manual loops or data formatting. For highly customized plots (complex layouts, custom color mappings, non-standard axes), matplotlib'sbar()is the way to go—it lets you tweak every element exactly how you want. - Default Behavior: Pandas' plot sets sensible defaults: it uses your Series/DataFrame index for x-axis labels, auto-generates legends, and aligns styling with pandas' data structure. Matplotlib requires you to manually set labels, legends, and axis adjustments—nothing is assumed.
Q1: How to set unique colors for each bar with the second method?
Pandas' plot.bar() accepts a color parameter that lets you pass a list of colors (one for each bar). You can define custom hex codes, use matplotlib's built-in color names, or even generate a gradient with a colormap.
Example with custom color list:
import pandas as pd import matplotlib.pyplot as plt # Calculate grouped medians median_data = df.groupby('index')['count'].median() # Define unique colors for each bar custom_colors = ['#ff7f0e', '#2ca02c', '#1f77b4', '#d62728', '#9467bd'] # Plot with unique colors median_data.plot.bar(color=custom_colors) # Add labels and title plt.xlabel('index') plt.ylabel('Median count') plt.title('Median count per index') plt.show()
Example with a colormap (gradient colors):
If you don’t want to pick colors manually, use a matplotlib colormap to generate a smooth gradient:
from matplotlib import cm import numpy as np n_bars = len(median_data) # Generate a range of colors from the viridis colormap gradient_colors = cm.viridis(np.linspace(0, 1, n_bars)) median_data.plot.bar(color=gradient_colors) plt.xlabel('index') plt.ylabel('Median count') plt.show()
Q2: How to remove gaps between bars with the first method?
The gaps happen because matplotlib’s bar() uses a default width of 0.8, and your original code plots each bar at the name value (e.g., 0,1,2,3,4) without adjusting positions to eliminate spacing. To fix this:
- Map your group names to consecutive integer positions (0,1,2,...)
- Set
width=1so each bar fills the entire space between x-axis ticks
Modified code:
import matplotlib.pyplot as plt groups = df.groupby('index') # Collect positions, medians, and labels first x_pos = [] medians = [] group_labels = [] for idx, (name, group) in enumerate(groups): x_pos.append(idx) medians.append(group['count'].median()) group_labels.append(name) # Plot with width=1 to eliminate gaps plt.bar(x_pos, medians, width=1, align='center') # Set x-axis ticks to show your original group names plt.xticks(x_pos, group_labels) plt.legend(group_labels) plt.xlabel('index') plt.ylabel('Median count') plt.title('Median count per index') plt.show()
This way, each bar will sit flush against the next, with no gaps between them.
内容的提问来源于stack exchange,提问作者user41855

