Pandas Python 按子组绘制条形图

1 投票
2 回答
1074 浏览
提问于 2025-04-18 14:12

好的,我有一个数据框对象,它的索引是这样的:

index,       rev,      metric1   (more metrics.....)

exp1,       92365,     0.018987  
exp2,       92365,    -0.070901  
exp3,       92365,     0.150140  
exp1,       87654,     0.003008  
exp2,       87654,    -0.065196   
exp3,       87654,    -0.174096

对于这些指标,我想创建单独的堆叠条形图,比较它们的收入。

这是我尝试过的:

df = df[['rev', 'metric1']]   
df = df.groupby("rev")  
df.plot(kind = 'bar') 

这样做的结果是两个单独的条形图。理想情况下,我希望这两个图合并成一个堆叠的图(现在设置堆叠为true没有任何效果)。如果能帮忙解决这个问题,我会非常感激。

这将给我理想的结果,不过我觉得为了达到这个目标而重新组织数据并不是最好的方法,因为我有很多指标和很多修订。

index,   metric1(rev87654), metric1(rev92365)
exp1,    0.018987,          0.003008 
exp2,   -0.070901,         -0.065196
exp3,    0.150140,         -0.174096

这是我的目标。(手动制作的)

https://i.stack.imgur.com/5GRqB.png

2 个回答

0

接下来是关于这个 matplotlib 示例的内容:

在这个示例中,他们通过对每一组数据调用一次 bar 函数来绘制多个柱状图。

你可以通过以下方式在 pandas 中访问这些值:

fig, ax = subplots(figsize=(16.2,10),dpi=300)
Y = Tire2[Tire2.SL==Tire2.SL.unique()[0]].SA.values[0:13]
X = linspace(0,size(Y),size(Y))

ax.bar(X,Y,width=.4)
Y = Tire2[Tire2.SL==Tire2.SL.unique()[2]].SA.values[0:13]
X = linspace(0,size(Y),size(Y))+.5
ax.bar(X,Y,width=.4,color='r')

从内到外来理解:

  1. 先获取某一列(在你的情况下是 rev 列)中所有独特的 'SL' 值。
  2. 得到一个布尔向量,表示所有 'SL' 等于第一个(或第 n 个)独特值的行。
  3. 用这个布尔向量来索引 Tire 数据,这样就只会提取出布尔向量为 True 的那些行。
  4. 访问 SA 的值,或者在你的情况下的某个指标。(我只取了 `[0:13]` 的值,因为我在一个很大的数据集上测试这个)
  5. 把这些值绘制成柱状图。

如果你的实验数据在框架中是有序的(就像展示的那样),那就没问题。否则,你可能需要稍微排序一下,以确保 Y 值的顺序正确。使用 .sort(列名) 就可以解决这个问题。在我的代码中,我会把它放在 ...[0]].SA... 之间。

总的来说,这种操作在处理大数据框时非常有帮助。.between 方法也很实用。而且你可以随时对布尔向量进行加法、乘法等操作,以构建更复杂的逻辑。

0

我不太确定如何能自动生成你想要的图,而不需要按照你最后提到的那样进行具体的重新组织。用户user3823992的回答可以让你对图表有更详细的控制,但如果你想要更自动化的方式,这里有一些临时的重新组织方法,可以使用类似的索引,同时也把结果合并回一个数据框,这样就能为你生成图表了。

import numpy as np
import pandas as pd

exp = ['exp1','exp2','exp3']*2
rev = [1,1,1,2,2,2]
met1 = np.linspace(-0.5,1,6)
met2 = np.linspace(1.0,5.0,6)
met3 = np.linspace(-1,1,6)
df = pd.DataFrame({'rev':rev, 'met1':met1, 'met2':met2, 'met3':met3}, index=exp)

for met in df.columns:
    if met != 'rev':
        merged = df[df['rev'] == df.rev.unique()[0]][met]
        merged.name = merged.name+'rev'+str(df.rev.unique()[0])
        for rev in df.rev.unique()[1:]:
            tmp = df[df['rev'] == rev][met]
            tmp.name = tmp.name+'rev'+str(rev)
            merged = pd.concat([merged, tmp], axis=1)

        merged.plot(kind='bar')

这样应该能给你生成三个图,每个图对应我虚构的一个指标。

编辑:或者类似这样的方式也可能有效

df['exp'] = df.index
pt = pd.pivot_table(df, values='met1', rows=['exp'], cols=['rev'])
pt.plot(kind='bar')

撰写回答