Tengo el siguiente conjunto de datos:

x = [0, 1, 2, 3, 4]
y = [ [0, 1, 2, 3, 4],
      [5, 6, 7, 8, 9],
      [9, 8, 7, 6, 5] ]

Ahora me parcela con:

import matplotlib.pyplot as plt
plt.plot(x, y)

Sin embargo, quiero etiquetar los 3 y los conjuntos de datos con este comando, lo que genera un error cuando .legend() se llama:

lineObjects = plt.plot(x, y, label=['foo', 'bar', 'baz'])
plt.legend()

File "./plot_nmos.py", line 33, in <module>
  plt.legend()
...
AttributeError: 'list' object has no attribute 'startswith'

Cuando me inspeccionar el lineObjects:

>>> lineObjects[0].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[1].get_label()
['foo', 'bar', 'baz']
>>> lineObjects[2].get_label()
['foo', 'bar', 'baz']

Pregunta

Hay una forma elegante para asignar varias etiquetas con sólo usar el .plot() método?

InformationsquelleAutor Kit | 2012-07-14

5 Comentarios

  1. 36

    No es posible graficar los dos matrices contra el uno al otro directamente (con al menos la versión 1.1.1), por lo tanto, usted debe ser un bucle por su y matrices. Mi consejo sería para recorrer las etiquetas al mismo tiempo:

    import matplotlib.pyplot as plt
    
    x = [0, 1, 2, 3, 4]
    y = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5] ]
    labels = ['foo', 'bar', 'baz']
    
    for y_arr, label in zip(y, labels):
        plt.plot(x, y_arr, label=label)
    
    plt.legend()
    plt.show()

    Edit: @gcalmettes señaló que como arrays de numpy, es posible trazar todas las líneas al mismo tiempo (por transposición de ellos). Ver a @gcalmettes respuesta & comentarios para más detalles.

    • +1 para el zip función 😉
  2. 46

    Usted puede iterar a través de su línea de la lista de objetos, por lo que las etiquetas son asignadas individualmente. Un ejemplo con el built-in de python iter función:

    lineObjects = plt.plot(x, y)
    plt.legend(iter(lineObjects), ('foo', 'bar', 'baz'))`

    Edición: después de actualizar a matplotlib 1.1.1, parece que el plt.plot(x, y), con y como una lista de listas (proporcionado por el autor de la pregunta), no funciona más. El paso de trazado sin iteración sobre el eje de matrices es posible todavía pensaba que después de pasar y como numpy.array (suponiendo (numpy)[http://numpy.scipy.org/] como ha sido previamente importados).

    En este caso, el uso de plt.plot(x, y) (si los datos en la matriz 2D y están dispuestas en forma de columnas [eje 1]) o plt.plot(x, y.transpose()) (si los datos en la matriz 2D y se disponen como filas [eje 0])

    Edit 2: como se señalaba en @pelson (ver comentario abajo), el iter función es innecesario y un simple plt.legend(lineObjects, ('foo', 'bar', 'baz')) funciona perfectamente

    • Esto no funciona para el usuario (la x y de y siempre no se pueden trazar al mismo tiempo, sin una iteración paso). Incluso si la representación que hizo de trabajo, suponiendo que la lineObjects es una lista o tupla etc.), el iter función sería innecesario.
    • de hecho, parece que no funciona con la nueva matplotlib liberación. Sin embargo, si x e y son numpy arrays, todavía se puede representar en un solo paso, con plot(x, y.transpose()). En este caso, la sintaxis con el iter función es todavía válida.
    • Su derecho, yo no sabía que una simple transposición de lo solucione. (arrays de numpy puede ser transportada con .T por la manera, es decir y.T). Sin embargo, mantengo la afirmación de que su iter función no es necesaria aquí (aunque es obvio que aún funciona).
    • tienes razón, un simple legend(lineObjects, ('foo', 'bar', 'baz')) trabaja perfectamente. No sé por qué he añadido el iter función aquí … gracias
  3. 29

    Me vino el mismo problema y ahora he encontrado una solución que es más fácil! Esperemos que no sea demasiado tarde para usted. No iterador, simplemente asignar el resultado a una estructura…

    from numpy import *
    from matplotlib.pyplot import *
    from numpy.random import *
    
    a = rand(4,4)
    a
    >>> array([[ 0.33562406,  0.96967617,  0.69730654,  0.46542408],
       [ 0.85707323,  0.37398595,  0.82455736,  0.72127002],
       [ 0.19530943,  0.4376796 ,  0.62653007,  0.77490795],
       [ 0.97362944,  0.42720348,  0.45379479,  0.75714877]])
    
    [b,c,d,e] = plot(a)
    legend([b,c,d,e], ["b","c","d","e"], loc=1)
    show()

    Se parece a esto:
    ¿Cómo puedo asignar varias etiquetas a la vez en matplotlib?

  4. 4

    Puede dar las etiquetas mientras que el trazado de las curvas

    import pylab as plt
    
    x = [0, 1, 2, 3, 4]
    y = [ [0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [9, 8, 7, 6, 5] ]
    labels=['foo', 'bar', 'baz']
    colors=['r','g','b']
    
    # loop over data, labels and colors
    for i in range(len(y)):
        plt.plot(x,y[i],'o-',color=colors[i],label=labels[i])
    
    plt.legend()
    plt.show()

    ¿Cómo puedo asignar varias etiquetas a la vez en matplotlib?

    • Estilísticamente, lo más probable es python para iterar sobre el eje de las listas directamente, comprimir otras listas al mismo tiempo (ver mi respuesta). Si usted realmente tiene, entonces en lugar de hacer un range(len(…)) es preferible utilizar enumerar(…). Usted todavía tiene un +1 a pesar de que 🙂
    • Gracias por señalarlo. En este caso izip, zip o enumerar hacen más sentido.
  5. 1

    En caso de numpy de la matriz de la trama asignar varias leyendas a la vez para cada columna

    Me gustaría responder a esta pregunta basada en el trazado de una matriz que tiene dos columnas.

    Decir que tiene usted la columna 2 de la matriz Ret

    entonces uno puede utilizar este código para asignar varias etiquetas a la vez

    import pandas as pd, numpy as np, matplotlib.pyplot as plt
    pd.DataFrame(Ret).plot()
    
    plt.xlabel('time')
    plt.ylabel('Return')
    plt.legend(['Bond Ret','Equity Ret'], loc=0)
    plt.show()

    Espero que esto ayude a

Dejar respuesta

Please enter your comment!
Please enter your name here