Bagaimana cara mendapatkan garis berwarna yang berbeda untuk plot yang berbeda dalam satu gambar?

202

Saya menggunakan matplotlibuntuk membuat plot. Saya harus mengidentifikasi setiap plot dengan warna berbeda yang harus dihasilkan secara otomatis oleh Python.

Bisakah Anda memberi saya metode untuk meletakkan warna berbeda untuk plot berbeda dalam gambar yang sama?

pottigopi
sumber

Jawaban:

424

Matplotlib melakukan ini secara default.

Misalnya:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)
plt.show()

Plot dasar menunjukkan siklus warna

Dan, seperti yang mungkin sudah Anda ketahui, Anda dapat dengan mudah menambahkan legenda:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Plot dasar dengan legenda

Jika Anda ingin mengontrol warna yang akan didaur ulang:

import matplotlib.pyplot as plt
import numpy as np

x = np.arange(10)

plt.gca().set_color_cycle(['red', 'green', 'blue', 'yellow'])

plt.plot(x, x)
plt.plot(x, 2 * x)
plt.plot(x, 3 * x)
plt.plot(x, 4 * x)

plt.legend(['y = x', 'y = 2x', 'y = 3x', 'y = 4x'], loc='upper left')

plt.show()

Plot menunjukkan kontrol atas siklus warna default

Jika Anda tidak terbiasa dengan matplotlib, tutorialnya adalah tempat yang baik untuk memulai .

Edit:

Pertama, jika Anda memiliki banyak (> 5) hal yang ingin Anda plot pada satu gambar, baik:

  1. Letakkan di plot yang berbeda (pertimbangkan untuk menggunakan beberapa sub plot pada satu gambar), atau
  2. Gunakan sesuatu selain warna (yaitu gaya marker atau ketebalan garis) untuk membedakannya.

Kalau tidak, Anda akan berakhir dengan plot yang sangat berantakan! Bersikaplah baik kepada siapa pun yang akan membaca apa pun yang Anda lakukan dan jangan mencoba menjejalkan 15 hal berbeda ke dalam satu angka !!

Selain itu, banyak orang yang buta warna sampai tingkat yang berbeda-beda, dan membedakan antara banyak warna yang agak berbeda sulit bagi lebih banyak orang daripada yang Anda sadari.

Yang telah dikatakan, jika Anda benar-benar ingin menempatkan 20 garis pada satu sumbu dengan 20 warna yang relatif berbeda, inilah salah satu cara untuk melakukannya:

import matplotlib.pyplot as plt
import numpy as np

num_plots = 20

# Have a look at the colormaps here and decide which one you'd like:
# http://matplotlib.org/1.2.1/examples/pylab_examples/show_colormaps.html
colormap = plt.cm.gist_ncar
plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))

# Plot several different functions...
x = np.arange(10)
labels = []
for i in range(1, num_plots + 1):
    plt.plot(x, i * x + 5 * i)
    labels.append(r'$y = %ix + %i$' % (i, 5*i))

# I'm basically just demonstrating several different legend options here...
plt.legend(labels, ncol=4, loc='upper center', 
           bbox_to_anchor=[0.5, 1.1], 
           columnspacing=1.0, labelspacing=0.0,
           handletextpad=0.0, handlelength=1.5,
           fancybox=True, shadow=True)

plt.show()

Warna unik untuk 20 garis berdasarkan colormap yang diberikan

Joe Kington
sumber
17
Catatan untuk contoh terakhir, dalam versi yang lebih baru dari matplotlib, set_color_cycletelah usang, sehingga baris seharusnya plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))dan hanya mengubah plt.cm.YOUR_PREFERED_COLOR_MAPsesuai dengan kebutuhan Anda.
Nate
1
@ JoKington: Penjelasannya luar biasa, Terima kasih banyak
Rika
ini bagus. apakah ada cara untuk menjadikannya interaktif? misalnya di RI, ggplot dikonversi menjadi ggplotly (), dan plot menjadi html interaktif
kRazzy R
Saya yakin bahwa OP tahu bahwa warna Matplotlib berbeda dengan kurva yang berbeda dalam satu plot (dalam satu axes) dan bertanya tentang memvariasikan warna garis tunggal dalam plot yang berbeda (berbeda axes) ... Yang mengatakan, jawaban yang sangat baik untuk yang penting pertanyaan (mungkin berbeda dari apa yang ditanyakan OP, tetapi tidak ada yang tahu karena mereka mengajukan satu pertanyaan ini dan menghilang!) - +1
gboffi
37

Pengaturan mereka nanti

Jika Anda tidak tahu jumlah plot yang akan Anda plot, Anda dapat mengubah warna setelah Anda memplotnya mengambil nomor langsung dari plot menggunakan .lines, saya menggunakan solusi ini:

Beberapa data acak

import matplotlib.pyplot as plt
import numpy as np

fig1 = plt.figure()
ax1 = fig1.add_subplot(111)


for i in range(1,15):
    ax1.plot(np.array([1,5])*i,label=i)

Potongan kode yang Anda butuhkan:

colormap = plt.cm.gist_ncar #nipy_spectral, Set1,Paired   
colors = [colormap(i) for i in np.linspace(0, 1,len(ax1.lines))]
for i,j in enumerate(ax1.lines):
    j.set_color(colors[i])
  

ax1.legend(loc=2)

Hasilnya adalah sebagai berikut:masukkan deskripsi gambar di sini

GM
sumber
8

TL; DR Tidak, itu tidak dapat dilakukan secara otomatis . Ya itu mungkin.

import matplotlib.pyplot as plt
my_colors = plt.rcParams['axes.prop_cycle']() # <<< note that we CALL the prop_cycle
fig, axes = plt.subplots(2,3)
for ax in axes.flatten(): ax.plot((0,1), (0,1), **next(my_colors))

masukkan deskripsi gambar di sini Setiap plot ( axes) dalam gambar ( figure) memiliki siklus warna sendiri - jika Anda tidak memaksakan warna yang berbeda untuk setiap plot, semua plot berbagi urutan warna yang sama, tetapi, jika kita merentangkan sedikit arti "otomatis" , itu bisa dilakukan.


OP menulis

[...] Saya harus mengidentifikasi setiap plot dengan warna berbeda yang harus dihasilkan secara otomatis oleh [Matplotlib].

Tapi ... Matplotlib secara otomatis menghasilkan warna yang berbeda untuk setiap kurva yang berbeda

In [10]: import numpy as np
    ...: import matplotlib.pyplot as plt

In [11]: plt.plot((0,1), (0,1), (1,2), (1,0));
Out[11]:

masukkan deskripsi gambar di sini

Jadi mengapa permintaan OP? Jika kita terus membaca, sudah

Bisakah Anda memberi saya metode untuk meletakkan warna berbeda untuk plot berbeda dalam gambar yang sama?

dan itu masuk akal, karena masing-masing plot (masing-masing axesdalam bahasa Matplotlib) memiliki sendiri color_cycle(atau lebih tepatnya, pada 2018, yang prop_cycle) dan masing-masing plot ( axes) menggunakan kembali warna yang sama dalam urutan yang sama.

In [12]: fig, axes = plt.subplots(2,3)

In [13]: for ax in axes.flatten():
    ...:     ax.plot((0,1), (0,1))

masukkan deskripsi gambar di sini

Jika ini adalah arti dari pertanyaan awal, satu kemungkinan adalah secara eksplisit memberi nama warna yang berbeda untuk setiap plot.

Jika plot (seperti yang sering terjadi) dihasilkan dalam satu loop, kita harus memiliki variabel loop tambahan untuk mengganti warna yang dipilih secara otomatis oleh Matplotlib.

In [14]: fig, axes = plt.subplots(2,3)

In [15]: for ax, short_color_name in zip(axes.flatten(), 'brgkyc'):
    ...:     ax.plot((0,1), (0,1), short_color_name)

masukkan deskripsi gambar di sini

Kemungkinan lain adalah untuk instantiate objek pengendara sepeda

from cycler import cycler
my_cycler = cycler('color', ['k', 'r']) * cycler('linewidth', [1., 1.5, 2.])
actual_cycler = my_cycler()

fig, axes = plt.subplots(2,3)
for ax in axes.flat:
    ax.plot((0,1), (0,1), **next(actual_cycler))

masukkan deskripsi gambar di sini

Perhatikan bahwa type(my_cycler)adalah cycler.Cyclertetapi type(actual_cycler)adalah itertools.cycle.

gboffi
sumber
3

Saya ingin menawarkan sedikit perbaikan pada jawaban loop terakhir yang diberikan pada posting sebelumnya (postingan itu benar dan masih harus diterima). Asumsi implisit yang dibuat ketika memberi label pada contoh terakhir adalah bahwa plt.label(LIST)menempatkan label nomor X LISTdengan garis yang sesuai dengan waktu X plotdisebut. Saya pernah mengalami masalah dengan pendekatan ini sebelumnya. Cara yang disarankan untuk membuat legenda dan menyesuaikan label mereka per dokumentasi matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) adalah memiliki perasaan hangat bahwa label tersebut pergi bersama dengan plot persis yang Anda pikir mereka lakukan:

...
# Plot several different functions...
labels = []
plotHandles = []
for i in range(1, num_plots + 1):
    x, = plt.plot(some x vector, some y vector) #need the ',' per ** below
    plotHandles.append(x)
    labels.append(some label)
plt.legend(plotHandles, labels, 'upper left',ncol=1)

**: Matplotlib Legends tidak berfungsi

Tommy
sumber
3
Hanya fyi: Anda juga dapat menggunakan "label" kwarg untuk merencanakan dan kemudian memanggil legenda tanpa argumen.
Joe Kington