Перечислите значения перечисления в кадре данных, используя сегментированную полосу pyplot - PullRequest
0 голосов
/ 15 мая 2018

У меня есть Серия (отметка времени, значение перечисления), описывающая, когда система находилась в данном состоянии; состояние описывается перечислением.

Time | State
--------------
  0  |   A
  3  |   B
  4  |   A
  7  |   C
  9  |   D

Я бы хотел визуализировать изменения состояния на гистограмме, заполняя каждое состояние вперед до следующей отметки времени и используя разные цвета для каждого значения перечисления:

|
|__________________________________________
|     A     | B |     A     |   C   |  D  |
|___________|___|___________|_______|_____|
|
---------------------------------------------
0   1   2   3   4   5   6   7   8   9   10   

Какой совет? Я посмотрел на Line Collection s и горизонтальные столбцы, но коллекции линий кажутся неуклюжими, а hbar, кажется, для скалярных значений. Я надеюсь найти элегантное идиоматическое решение.

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Я придумал решение, которое использует LineCollection. Моя неудовлетворенность этим заключается в том, что элементы LineCollection кажутся не зависящими от масштаба (они имеют одинаковую ширину независимо от масштаба по оси Y), что затрудняет манипулирование. Из-за этого недостатка, я думаю, я предпочитаю барное решение.

Horizontal bar plot with states represented as colors, and lengths of bars representing the duration that state was valid for.

import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.patches as mpatches
import pandas as pd

df = pd.DataFrame(zip([0, 3, 4, 7, 9, 12], ['A', 'B', 'A', 'C', 'D', 'A']), 
                  columns=['Time', 'State'])

df['Duration'] = df['Time'].shift(-1) - df['Time']

# Showing how we can use HTML color names
state_to_color_map = {
    'A': 'LightBlue',
    'B': 'gray',
    'C': 'LightPink',
    'D': 'MediumSeaGreen'
}
fig = plt.figure(figsize=(8, 4))
ax = fig.gca()

plot_height = 0  # Can loop this to plot multiple bars

for state, state_color in state_to_color_map.iteritems():
  segments = [[(start, plot_height), (start + duration, plot_height)] for 
              (start, duration) in 
              df[df['State'] == state][['Time', 'Duration']].values]
  plot_segments = mpl.collections.LineCollection(
      segments=segments,
      # In matplotlib 2.2.2, this code is `mcolors.to_rgba(...)`
      # Use this code for matplotlib 1.5.3.
      colors=[mcolors.colorConverter.to_rgba(state_color)] * len(segments),
      linewidths=50)
  ax.add_collection(plot_segments)

ax.set_ylim(-1, 1)
ax.set_xlim(0, 12)

# Legend
patches = []
for state, color in sorted(state_to_color_map.iteritems()):
  patches.append(mpatches.Patch(color=color, label=state))
ax.legend(handles=patches, bbox_to_anchor=(1.10, 0.5), loc='center', 
          borderaxespad=0.)
0 голосов
/ 15 мая 2018

Вы можете создавать гистограммы с указанием левой начальной точки и ширины:

color = {'A': 'red', 'B': 'green', 'C': 'blue', 'D': 'yellow'}
for s, t, c in list(zip(df.State, df.Time.shift(-1) - df.Time, df.Time))[: -1]:
    bar(left=c, height=0.8, width=t, bottom=0, color=color[s], orientation="horizontal", label=s)
    print(c, t)
legend();

enter image description here

Вы также можете позвонить

get_yaxis().set_visible(False)

используйте лучшие цвета и сделайте эту фигуру менее уродливой (трудно сделать ее более некрасивой).

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