Pandas- 在给定条形图中的列名称的子结果中绘制结果,并将值放在每个条形图的顶部

Pandas- plot results in sub results given a column name in a barplot and put value on top of each bar

我在 csv 文件中有非常简单的数据集

condition,method,error
Normalized,LinfPGD,100
Integer,LinfPGD,100
Print+Scan(U),LinfPGD,59
Print+Scan(P),LinfPGD,9
Normalized,LinfBasicInteractive,100
Integer,LinfBasicInteractive,100
Print+Scan(U),LinfBasicInteractive,69
Print+Scan(P),LinfBasicInteractive,9

我想在 pandas 中的条形图中绘制它,但将“方法”列作为主要结果,将“条件”列作为子结果,将“错误”作为要绘制的值.

我最接近的是使用交叉表

data=pd.read_csv('my_results.csv', sep=",")
pd.crosstab(data['method'], data['condition']).plot.bar(color=('DarkBlue', 'LightBlue', 'Teal'))
plt.tight_layout()
plt.show()

哪个returns我这个

这不是我想要的,因为交叉表会计算每个“条件”的数量,而我不希望这样。我想要的只是考虑每个“方法”为每个“条件”绘制“错误”列。我还想将值放在每个栏的顶部。如何使用 Pandas/Matplotlib/Seaborn?

我想我们可以使用 Pivot 转换数据框并创建图表。

data = data.pivot(index='method', columns='condition', values='error')
data.plot.bar(color=('DarkBlue', 'LightBlue', 'Teal'))

您可以直接从原始数据框创建一个 seaborn 条形图:

from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
from io import StringIO

data_str = '''condition,method,error
Normalized,LinfPGD,100
Integer,LinfPGD,100
Print+Scan(U),LinfPGD,59
Print+Scan(P),LinfPGD,9
Normalized,LinfBasicInteractive,100
Integer,LinfBasicInteractive,100
Print+Scan(U),LinfBasicInteractive,69
Print+Scan(P),LinfBasicInteractive,9'''
data = pd.read_csv(StringIO(data_str), delimiter=',')
plt.figure(figsize=(12, 4))
sns.set_style('darkgrid')
ax = sns.barplot(data=data, x='method', y='error', hue='condition', palette=['darkblue', 'lightblue', 'teal'])
for bars in ax.containers:
    ax.bar_label(bars)
ax.margins(y=0.1) # some extra space for the labels
plt.tight_layout()
plt.show()