2012-01-07 13 views
10

Ho 3 elenchi, ciascuno contenente numeri, che rappresentano un orario. Il tempo rappresenta l'occorrenza di un evento. Ad esempio, in questo A, ho un numero per ogni occorrenza dell'evento A. Voglio rappresentare questi dati su un grafico. In uno dei seguenti due modi:Come stampare gli eventi in tempo con l'utilizzo di matplotlib

1)

aabaaabbccacac 

2)

a-> xx xxx x x 
b-> x xx 
c->   xx x x 

risposta

10

Tu co ULD uso plt.hlines:

import matplotlib.pyplot as plt 
import random 
import numpy as np 
import string 

def generate_data(N = 20): 
    data = [random.randrange(3) for x in range(N)] 
    A = [i for i, x in enumerate(data) if x == 0] 
    B = [i for i, x in enumerate(data) if x == 1] 
    C = [i for i, x in enumerate(data) if x == 2] 
    return A,B,C 

def to_xy(*events): 
    x, y = [], [] 
    for i,event in enumerate(events): 
     y.extend([i]*len(event)) 
     x.extend(event) 
    x, y = np.array(x), np.array(y) 
    return x,y 

def event_string(x,y): 
    labels = np.array(list(string.uppercase))   
    seq = labels[y[np.argsort(x)]] 
    return seq.tostring() 

def plot_events(x,y): 
    labels = np.array(list(string.uppercase))  
    plt.hlines(y, x, x+1, lw = 2, color = 'red') 
    plt.ylim(max(y)+0.5, min(y)-0.5) 
    plt.yticks(range(y.max()+1), labels) 
    plt.show() 

A,B,C = generate_data(20) 
x,y = to_xy(A,B,C) 
print(event_string(x,y)) 
plot_events(x,y) 

cede

BBACBCACCABACCBCABCC 

enter image description here

3

Questo è un approccio che si può partire da:

from matplotlib import pyplot as plt 

A = [23,45,56,78,32,11] 
B = [44,56,78,98] 
C = [23,46,67,79] 

x = [] 
y = [] 
for idx, lst in enumerate((A, B, C)): 
    for time in lst: 
     x.append(time) 
     y.append(idx) 

plt.ylim((-3,5)) 
plt.yticks([0, 1, 2], ['A', 'B', 'C']) 
plt.scatter(x,y, color='r', s=70) 
plt.show() 

enter image description here

2

Si potrebbe prendere in considerazione il display orario dei treni utilizzati sulla copertina di Edward Tufte di The Visual Display of Quantitative Information. Ciò è utile per mostrare il tasso di cambiamento degli eventi in momenti diversi (vedere la spiegazione a pagina 31, 2a edizione), ma ciò è rilevante solo se i tuoi eventi si verificano in momenti irregolari.

In entrambi i casi, le altre risposte forniscono buone opzioni per la seconda richiesta. Si può semplicemente voler tracciare linee, con il comando pyplot (o assi) plot(x). Puoi cambiare le etichette come mostrato nelle altre risposte in modo che siano testo che rappresenta i tuoi eventi. Infine, per emulare l'effetto mostrato nella figura del programma del treno, è possibile impostare una griglia utilizzando il metodo pyplot grid (o axes.xaxis.grid).

14

Come estensione alle risposte precedenti, è possibile utilizzare plt.hbar:

import matplotlib.pyplot as plt 
import numpy as np 
import string 

x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]) 
y = np.array([0, 0, 1, 0, 0, 0, 1, 1, 2, 2, 0, 2, 0, 2]) 

labels = np.array(list(string.uppercase))  
plt.barh(y, [1]*len(x), left=x, color = 'red', edgecolor = 'red', align='center', height=1) 
plt.ylim(max(y)+0.5, min(y)-0.5) 
plt.yticks(np.arange(y.max()+1), labels) 
plt.show() 

enter image description here

Oppure, si potrebbe provare quarantina in questo modo:

import matplotlib.pyplot as plt 
import numpy as np 

data = [[1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0], 
     [0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 3, 0, 3]] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.axes.get_yaxis().set_visible(False) 
ax.set_aspect(1) 

def avg(a, b): 
    return (a + b)/2.0 

for y, row in enumerate(data): 
    for x, col in enumerate(row): 
     x1 = [x, x+1] 
     y1 = np.array([y, y]) 
     y2 = y1+1 
     if col == 1: 
      plt.fill_between(x1, y1, y2=y2, color='red') 
      plt.text(avg(x1[0], x1[1]), avg(y1[0], y2[0]), "A", 
             horizontalalignment='center', 
             verticalalignment='center') 
     if col == 2: 
      plt.fill_between(x1, y1, y2=y2, color='orange') 
      plt.text(avg(x1[0], x1[0]+1), avg(y1[0], y2[0]), "B", 
             horizontalalignment='center', 
             verticalalignment='center') 
     if col == 3: 
      plt.fill_between(x1, y1, y2=y2, color='yellow') 
      plt.text(avg(x1[0], x1[0]+1), avg(y1[0], y2[0]), "C", 
             horizontalalignment='center', 
             verticalalignment='center') 

plt.ylim(3, 0) 
plt.show() 

enter image description here

Se vuoi tutte le slot essere sulla stessa riga, basta fare alcune modifiche come illustrato di seguito:

import matplotlib.pyplot as plt 
import numpy as np 

data = [[1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0], 
     [0, 0, 2, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0], 
     [0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 3, 0, 3]] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.axes.get_yaxis().set_visible(False) 
ax.set_aspect(1) 

def avg(a, b): 
    return (a + b)/2.0 

for y, row in enumerate(data): 
    for x, col in enumerate(row): 
     x1 = [x, x+1] 
     y1 = [0, 0] 
     y2 = [1, 1] 
     if col == 1: 
      plt.fill_between(x1, y1, y2=y2, color='red') 
      plt.text(avg(x1[0], x1[1]), avg(y1[0], y2[0]), "A", 
             horizontalalignment='center', 
             verticalalignment='center') 
     if col == 2: 
      plt.fill_between(x1, y1, y2=y2, color='orange') 
      plt.text(avg(x1[0], x1[0]+1), avg(y1[0], y2[0]), "B", 
             horizontalalignment='center', 
             verticalalignment='center') 
     if col == 3: 
      plt.fill_between(x1, y1, y2=y2, color='yellow') 
      plt.text(avg(x1[0], x1[0]+1), avg(y1[0], y2[0]), "C", 
             horizontalalignment='center', 
             verticalalignment='center') 

plt.ylim(1, 0) 
plt.show() 

enter image description here

La seconda e la terza opzione sono più codice, ma si ottengano risultati molto migliori.

+0

+1 per inchiodare la prima richiesta alla tua ultima trama. – Yann

+0

c'è un nome (ad esempio grafico a barre in pila, grafico a linee area, ecc.) Per l'ultimo tipo di grafico? – arturomp

0

Sulla base e la semplificazione ultimo grafico @amillerrhodes' (eliminando la parte di testo anche):

import matplotlib.pyplot as plt 
import numpy as np 

# run-length encoding, instead of a list of lists with a bunch of zeros 
data = [(2, 1), (1, 2), (3, 1), (2, 2), (2, 3), (1, 1), (1, 3), (1, 1), (1, 3)] 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.axes.get_yaxis().set_visible(False) 
ax.set_aspect(1) 

for i, (num, cat) in enumerate(data): 

    if i > 0: 
     x_start += data[i-1][0] # get previous end position 
    else: 
     x_start = i    # start from 0 

    x1 = [x_start, x_start+num] 

    y1 = [0, 0] 
    y2 = [1, 1] 

    if cat == 1: 
     plt.fill_between(x1, y1, y2=y2, color='red') 
    if cat == 2: 
     plt.fill_between(x1, y1, y2=y2, color='orange') 
    if cat == 3: 
     plt.fill_between(x1, y1, y2=y2, color='yellow') 

plt.ylim(1, 0) 
plt.show() 

enter image description here

Problemi correlati