Изменить сложенную легенду линейного графика в Python - PullRequest
1 голос
/ 01 мая 2019

У меня есть следующие данные в CSV-файле:

Date    City    TruckA  TruckB  TruckC  TruckD
Date1   City1   1   0   0   0
Date1   City2   0   0   1   0
Date1   City3   1   0   0   0
Date1   City4   0   0   1   0
Date2   City1   1   0   0   0
Date2   City2   0   1   0   0
Date2   City3   0   0   0   1
Date2   City4   1   0   0   0
Date2   City5   0   1   0   0
Date3   City1   1   0   0   0
Date3   City2   0   0   1   0
Date3   City3   1   0   0   0
Date3   City4   0   0   1   0

Я могу успешно построить данные с этим кодом:

import pandas as pd

df = pd.read_csv("data.csv")

print(df)

df = df.set_index(["Date","City"])

df.unstack().plot(kind='bar', stacked=True)

Я получаю следующий результат: image

Как видите, цветовая легенда такова, что каждая пара (Город, Грузовик) имеет свой цвет.Мне бы хотелось, чтобы легенда зависела только от Грузовика, и в идеале иметь метки на гистограмме для каждого города.

Возможно ли это?

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Следуя великолепному ответу @ Скотта, вы можете получить столбцы с накоплением по желанию.

import matplotlib.pyplot as plt
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
df_out = df.unstack()
d = dict(zip(df.columns.get_level_values(0),cycle))
c = df_out.columns.get_level_values(0).map(d)
g=df_out.plot.bar(stacked=True, color=c, figsize=(10,8), edgecolor='k')

Чтобы добавить метки, вам нужно найти правильную позицию и метить итеративно.
Вот один из способовсделать это:

РЕДАКТИРОВАТЬ: только один цикл

h=0
x=0
unique_dates=df1.index.get_level_values(0).unique() # get the bars
city=df_out.iloc[x][df_out.iloc[x]!=0].dropna().index.get_level_values(1) #get the cities
for y,val in enumerate(df1.index.get_level_values(0)): #loop through the dates
    if val==unique_dates[x]: #check the x position
        g.text(x-0.05,1+h-0.5,"%s" % city[h]) 
        h+=1
    else:                                             # move to next x coord, update city labels and add text for the next x coordinate (h=0)
        x+=1
        city=df_out.iloc[x][df_out.iloc[x]!=0].dropna().index.get_level_values(1) #get cities
        g.text(x-0.05,1-0.5,"%s" % city[0])
        h=1      # set h to 1 as we already printed for h=0

Исходное решение

for x ,date in enumerate(df_out.index):
    h=0
    city=df_out.iloc[x][df_out.iloc[x]!=0].dropna().index.get_level_values(1) #get cities
    for y,val in enumerate(df.index.get_level_values(0)):
        if val==date:
            g.text(x,1+h-0.5,"%s" % city[h])
            h+=1
        else:
            continue

image

2 голосов
/ 01 мая 2019

Редактировать

import matplotlib.pyplot as plt
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
df_out = df.unstack()
d = dict(zip(df.columns.get_level_values(0),cycle))
c = df_out.columns.get_level_values(0).map(d)
df_out.plot.bar(stacked=True, color=c, figsize=(10,8))

Вывод:

enter image description here

Добавлен цвет границ для разделения городов:

import matplotlib.pyplot as plt
cycle = plt.rcParams['axes.prop_cycle'].by_key()['color']
df_out = df.unstack()
d = dict(zip(df.columns.get_level_values(0),cycle))
c = df_out.columns.get_level_values(0).map(d)
df_out.plot.bar(stacked=True, color=c, figsize=(10,8), edgecolor='k')

enter image description here


IIUC, я думаю, вы ищете что-то вроде этого:

df = df.set_index(["Date","City"])
df.sum(level=0).plot.bar(stacked=True, figsize=(10,8))

Вывод:

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...