모든 플롯이 다른 열의 값에 해당하는 열의 모든 값에 대해 다른 막대를 그리는 방법은 무엇입니까?

Dec 04 2020

이 데이터 프레임은 아래와 같습니다.

data = [['AK','Coal',24457],
['AK','Natural ',222867],
['AK','Other ',15],
['AK','Petro',83848],
['AL','Coal ',169877],
['AL','Natural ',10692],
['AL','Other ',2631],
['AL','Petro',235853]]

df = pd.DataFrame(data, columns = ['STATE','ENERGY','CONSUME']) 

이 이미지와 같은 모양이 필요한 그래프에 플롯하려고합니다.

모든 막대는 해당 '에너지'에 대한 '소모'값에 해당합니다. 이는 'STATE'를 기준으로 값을 그룹화하고 'ENERGY'를 기준으로 다른 막대를 그리는 것과 같습니다. 따라서 기본적으로 모든 'STATE'에는 4 개의 서로 다른 'ENERGY'값을 나타내는 4 개의 막대가 있습니다. 몇 가지를 시도했지만 내가 원하는 방식으로 작동하지 않았습니다.

답변

Pygirl Dec 04 2020 at 15:30

나는 Scott Boston 이 그의 대답 중 하나에서 제공 한 코드를 수정하고 있습니다 . 그 대답도 살펴보십시오.

import pandas as pd
import matplotlib.pyplot as plt
from itertools import groupby
import numpy as np 
%matplotlib inline

data = [['AK','Coal',24457],
['AK','Natural ',222867],
['AK','Other ',15],
['AK','Petro',83848],
['AL','Coal ',169877],
['AL','Natural ',10692],
['AL','Other ',2631],
['AL','Petro',235853]]
df = pd.DataFrame(data, columns = ['STATE','ENERGY','CONSUME']) 
df = df.set_index(['STATE','ENERGY', 'STATE'])['CONSUME'].unstack()


def add_line(ax, xpos, ypos):
    line = plt.Line2D([xpos, xpos], [ypos + .1, ypos],
                      transform=ax.transAxes, color='gray')
    line.set_clip_on(False)
    ax.add_line(line)

def label_len(my_index,level):
    labels = my_index.get_level_values(level)
    return [(k, sum(1 for i in g)) for k,g in groupby(labels)]

def label_group_bar_table(ax, df):
    ypos = -.1
    scale = 1./df.index.size
    for level in range(df.index.nlevels)[::-1]:
        pos = 0
        for label, rpos in label_len(df.index,level):
            lxpos = (pos + .5 * rpos)*scale
            ax.text(lxpos, ypos, label, ha='center', transform=ax.transAxes)
            add_line(ax, pos*scale, ypos)
            pos += rpos
        add_line(ax, pos*scale , ypos)
        ypos -= .1

ax = df.plot(kind='bar')
#Below 2 lines remove default labels
ax.set_xticklabels('')
ax.set_xlabel('')
label_group_bar_table(ax, df)