Question: I am still an absolute beginner in python and I googled a lot to built code to make a stacked bar chart plot my df. I am using spyder and python 3.12 After some data preparation, I am left with this df: {'storage': {0: 'a', 2: 'a', 3: 'a', 4: 'b', 5: 'b'}, 'time': {0: '4h', 2: '4h', 3: '4h', 4: '4h', 5: '4h'}, 'Predicted Class': {0: 'germling', 2: 'resting', 3: 'swollen', 4: 'germling', 5: 'hyphae'}, '%': {0: 0.22, 2: 99.02, 3: 0.76, 4: 65.41, 5: 1.72}}  I prepare it with pivoting for plotting as a stacked bar chart. class_order = ['resting', 'swollen', 'germling', 'hyphae', 'mature hyphae'] counts2_reduced_df['Predicted Class'] = pd.Categorical(counts2_reduced_df['Predicted Class'], categories=class_order, ordered=True) counts2_pivot_df = counts2_reduced_df.pivot_table(index=["storage","time"], columns="Predicted Class", values="%", aggfunc="sum")  This leaves me with this df that now contains to cells with 0 as values that I would like to prevent from being plotted. When I plot this df now, I get the following plot (it still has other issues like making the values of the small percentages readable, but this is an issue for another post I guess).  I tried different approaches like converting 0s to nas and then drop.na of course removes the entire rows, but I would like to only prevent the cells containing 0s from being plotted / shown in the plot. I tried counts2_pivot_df = counts2_pivot_df.replace(0, "") but it prevents the columns "hyphae" and "mature hyphae" completely from being plotted. {'resting': {('a', '4h'): 99.02, ('b', '4h'): 2.57, ('c', '4h'): 2.19}, 'swollen': {('a', '4h'): 0.76, ('b', '4h'): 30.19, ('c', '4h'): 25.57}, 'germling': {('a', '4h'): 0.22, ('b', '4h'): 65.41, ('c', '4h'): 70.67}, 'hyphae': {('a', '4h'): '', ('b', '4h'): 1.72, ('c', '4h'): 1.47}, 'mature hyphae': {('a', '4h'): '', ('b', '4h'): 0.11, ('c', '4h'): 0.1}}   Is there a way for solving this issue? I have read and tried many posts but cannot come up with a solution. EDIT: This is the code I use to create the plots: fig, ax = plt.subplots() # Colors for each class, color_mapping = { 'resting': 'yellow', 'swollen': 'blue', 'germling': 'red', 'hyphae': 'cyan', 'mature hyphae': 'green', } # Colors for each class using the mapping colors = [color_mapping[class_name] for class_name in class_order] # Ensure colors follow the same order # Plotting the stacked bars counts2_pivot_df.plot(kind='bar', stacked=True, color=colors, ax=ax) # Set x-tick labels correctly based on the pivot index ax.set_xticks(range(len(counts2_pivot_df.index))) ax.set_xticklabels([f'{i[0]} & {i[1]}' for i in counts2_pivot_df.index], rotation=0) ax.set_xlabel('Storage Condition and Time after Inoculation') ax.set_ylabel('Percentage (%)') plt.xticks(rotation=360) plt.legend(title='Predicted Class') ax.legend(loc='center left', bbox_to_anchor=(1, 0.5)) # Annotating percentages for n, bar_group in enumerate(ax.containers): for bar in bar_group: height = bar.get_height() text_x = bar.get_x() + bar.get_width() / 2 text_y = bar.get_y() + height / 2 ha = 'center' if height > 5 else 'left' va = 'center' text_x_adjusted = text_x if height > 5 else bar.get_x() + bar.get_width() ax.annotate(f'{height:.2f}%', xy=(text_x_adjusted, text_y), ha=ha, va=va, color='black', fontsize=8, fontweight='bold') plt.show() 

Answer: Since you are plotting the labels manually, an easy option is to add a continue in your loop when the height is null:  for bar in bar_group: height = bar.get_height() if height == 0: continue text_x = bar.get_x() + bar.get_width() / 2 text_y = bar.get_y() + height / 2 ha = 'center' if height > 5 else 'left' va = 'center' text_x_adjusted = text_x if height > 5 else bar.get_x() + bar.get_width() ax.annotate(f'{height:.2f}%', xy=(text_x_adjusted, text_y), ha=ha, va=va, color='black', fontsize=8, fontweight='bold')  Output: