Làm thế nào để có được các dòng màu khác nhau cho các ô khác nhau trong một hình duy nhất?


202

Tôi đang sử dụng matplotlibđể tạo ra các mảnh đất. Tôi phải xác định mỗi ô với một màu khác nhau sẽ được Python tự động tạo.

Bạn có thể vui lòng cho tôi một phương pháp để đặt các màu khác nhau cho các ô khác nhau trong cùng một hình không?

Câu trả lời:


424

Matplotlib làm điều này theo mặc định.

Ví dụ:

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()

Cốt truyện cơ bản thể hiện màu sắc đi xe đạp

Và, như bạn có thể đã biết, bạn có thể dễ dàng thêm một huyền thoại:

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()

Cốt truyện cơ bản với truyền thuyết

Nếu bạn muốn kiểm soát màu sắc sẽ được chuyển qua:

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()

Lô đất hiển thị quyền kiểm soát đối với chu kỳ màu mặc định

Nếu bạn không quen thuộc với matplotlib, hướng dẫn là một nơi tốt để bắt đầu .

Biên tập:

Trước hết, nếu bạn có nhiều (> 5) thứ bạn muốn vẽ trên một hình, thì:

  1. Đặt chúng trên các ô khác nhau (xem xét sử dụng một vài ô nhỏ trên một hình), hoặc
  2. Sử dụng một cái gì đó ngoài màu sắc (tức là kiểu đánh dấu hoặc độ dày đường kẻ) để phân biệt giữa chúng.

Nếu không, bạn sẽ kết thúc với một âm mưu rất lộn xộn! Hãy tử tế với những người sẽ đọc bất cứ điều gì bạn đang làm và đừng cố nhồi nhét 15 thứ khác nhau vào một hình !!

Ngoài ra, nhiều người bị mù màu ở các mức độ khác nhau và việc phân biệt giữa nhiều màu sắc khác nhau rất khó đối với nhiều người hơn bạn có thể nhận ra.

Điều đó đã được nói, nếu bạn thực sự muốn đặt 20 dòng trên một trục với 20 màu tương đối khác biệt, đây là một cách để làm điều đó:

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()

Màu sắc độc đáo cho 20 dòng dựa trên một bản đồ màu


17
Lưu ý cho ví dụ cuối cùng, trong các phiên bản mới hơn của matplotlib, phần set_color_cyclenày đã bị phản đối, vì vậy dòng đó phải plt.gca().set_prop_cycle(plt.cycler('color', plt.cm.jet(np.linspace(0, 1, num_plots))))và chỉ thay đổi plt.cm.YOUR_PREFERED_COLOR_MAPcho phù hợp với nhu cầu của bạn.
Nate

1
@JoeKington: Lời giải thích thật tuyệt vời, Cảm ơn bạn rất nhiều
Rika

điều đó thật tuyệt. Có cách nào để làm cho chúng tương tác? ví dụ: trong RI chuyển đổi ggplot thành ggplotly () và cốt truyện trở thành tương tác html
kRazzy R

Tôi tin rằng OP biết rằng các màu Matplotlib thích hợp các đường cong khác nhau trong một ô duy nhất (trong một ô axes) và hỏi về việc thay đổi màu của một dòng trong các ô khác nhau (khác nhau axes) ... Điều đó nói rằng, câu trả lời tuyệt vời cho một điều quan trọng câu hỏi (có thể khác với những gì OP đã hỏi, nhưng không ai có thể nói vì họ đã hỏi câu hỏi này và biến mất!) - +1
gboffi

37

Đặt chúng sau

Nếu bạn không biết số lô bạn sẽ vẽ, bạn có thể thay đổi màu sắc sau khi bạn đã vẽ chúng lấy số trực tiếp từ lô bằng cách sử dụng .lines, tôi sử dụng giải pháp này:

Một số dữ liệu ngẫu nhiên

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)

Đoạn mã mà bạn cần:

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)

Kết quả là như sau:nhập mô tả hình ảnh ở đây


8

TL; DR Không, nó không thể được thực hiện tự động . Vâng, nó là có thể.

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))

nhập mô tả hình ảnh ở đây Mỗi ô ( axes) trong hình ( figure) có chu kỳ màu riêng - nếu bạn không buộc một màu khác nhau cho mỗi ô, tất cả các ô đều có chung một thứ tự màu, nhưng nếu chúng ta kéo dài một chút thì "tự động" nghĩa là gì , nó có thể được thực hiện.


OP đã viết

[...] Tôi phải xác định mỗi ô có một màu khác nhau sẽ được tự động tạo bởi [Matplotlib].

Nhưng ... Matplotlib tự động tạo ra các màu khác nhau cho mỗi đường cong khác nhau

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]:

nhập mô tả hình ảnh ở đây

Vậy tại sao OP yêu cầu? Nếu chúng ta tiếp tục đọc, chúng ta có

Bạn có thể vui lòng cho tôi một phương pháp để đặt các màu khác nhau cho các ô khác nhau trong cùng một hình không?

và nó có ý nghĩa, bởi vì mỗi âm mưu (mỗi axesô theo cách nói của Matplotlib) đều có color_cycle(hoặc đúng hơn là vào năm 2018 prop_cycle) và mỗi ô ( axes) sử dụng lại các màu giống nhau theo cùng một thứ tự.

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

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

nhập mô tả hình ảnh ở đây

Nếu đây là ý nghĩa của câu hỏi ban đầu, một khả năng là đặt tên rõ ràng cho một màu khác nhau cho mỗi âm mưu.

Nếu các ô (như thường xảy ra) được tạo trong một vòng lặp, chúng ta phải có một biến vòng lặp bổ sung để ghi đè màu được tự động chọn bởi 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)

nhập mô tả hình ảnh ở đây

Một khả năng khác là khởi tạo một đối tượng cycler

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))

nhập mô tả hình ảnh ở đây

Lưu ý đó type(my_cycler)cycler.Cyclernhưng type(actual_cycler)itertools.cycle.


3

Tôi muốn cung cấp một cải tiến nhỏ về câu trả lời vòng lặp cuối cùng được đưa ra trong bài viết trước (bài đăng đó là chính xác và vẫn nên được chấp nhận). Giả định ngầm định được thực hiện khi dán nhãn ví dụ cuối cùng là plt.label(LIST)đặt nhãn số X LISTvới dòng tương ứng với lần thứ X plotđược gọi. Tôi đã gặp vấn đề với cách tiếp cận này trước đây. Cách được đề xuất để xây dựng các huyền thoại và tùy chỉnh nhãn của họ theo tài liệu matplotlibs ( http://matplotlib.org/users/legend_guide.html#adjusting-the-order-of-legend-item ) là cảm giác ấm áp khi các nhãn đi cùng với các lô chính xác mà bạn nghĩ rằng chúng làm:

...
# 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 không hoạt động


3
Chỉ cần fyi: bạn cũng có thể sử dụng kwarg "nhãn" để vẽ và sau đó gọi huyền thoại mà không có bất kỳ đối số.
Joe Kington
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.