Cách tạo màu tùy chỉnh cho biểu đồ thanh pandas / matplotlib


85

Tôi vừa mới bắt đầu sử dụng pandas / matplotlib thay thế cho Excel để tạo biểu đồ thanh xếp chồng lên nhau. Tôi đang gặp sự cố

(1) chỉ có 5 màu trong bản đồ màu mặc định, vì vậy nếu tôi có nhiều hơn 5 loại thì các màu sẽ lặp lại. Làm thế nào tôi có thể chỉ định nhiều màu hơn? Lý tưởng nhất, một gradient có màu bắt đầu và màu kết thúc và cách tạo động n màu ở giữa?

(2) màu sắc không đẹp mắt. Làm cách nào để chỉ định một tập hợp n màu tùy chỉnh? Hoặc, một gradient cũng sẽ hoạt động.

Dưới đây là một ví dụ minh họa cả hai điểm trên:

  4 from matplotlib import pyplot
  5 from pandas import *
  6 import random
  7 
  8 x = [{i:random.randint(1,5)} for i in range(10)]
  9 df = DataFrame(x)
 10 
 11 df.plot(kind='bar', stacked=True)

Và kết quả là:

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


Có một cách khá dễ dàng để có được một phần sơ đồ màu. Xem giải pháp dưới đây
Ted Petrou

Câu trả lời:


118

Bạn có thể chỉ định colortùy chọn dưới dạng danh sách trực tiếp cho plothàm.

from matplotlib import pyplot as plt
from itertools import cycle, islice
import pandas, numpy as np  # I find np.random.randint to be better

# Make the data
x = [{i:np.random.randint(1,5)} for i in range(10)]
df = pandas.DataFrame(x)

# Make a list by cycling through the colors you care about
# to match the length of your data.
my_colors = list(islice(cycle(['b', 'r', 'g', 'y', 'k']), None, len(df)))

# Specify this list of colors as the `color` option to `plot`.
df.plot(kind='bar', stacked=True, color=my_colors)

Để xác định danh sách tùy chỉnh của riêng bạn, bạn có thể thực hiện một số thao tác sau đây hoặc chỉ cần tra cứu các kỹ thuật Matplotlib để xác định một mục màu theo các giá trị RGB của nó, v.v. Bạn có thể phức tạp như bạn muốn với điều này.

my_colors = ['g', 'b']*5 # <-- this concatenates the list to itself 5 times.
my_colors = [(0.5,0.4,0.5), (0.75, 0.75, 0.25)]*5 # <-- make two custom RGBs and repeat/alternate them over all the bar elements.
my_colors = [(x/10.0, x/20.0, 0.75) for x in range(len(df))] # <-- Quick gradient example along the Red/Green dimensions.

Ví dụ cuối cùng tạo ra gradient màu đơn giản sau đây cho tôi:

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

Tôi đã không chơi với nó đủ lâu để tìm ra cách buộc chú giải chọn các màu đã xác định, nhưng tôi chắc rằng bạn có thể làm được.

Tuy nhiên, nói chung, một lời khuyên lớn là chỉ sử dụng trực tiếp các chức năng từ Matplotlib. Gọi cho họ từ Pandas là được, nhưng tôi thấy bạn có các tùy chọn và hiệu suất tốt hơn khi gọi họ trực tiếp từ Matplotlib.


3
Lỗi nhỏ: my_colors = [cycle (['b', 'r', 'g', 'y', 'k']). Next () cho tôi trong phạm vi (len (df))] sẽ cho 'b' mọi lúc trong python 2.7. Bạn nên sử dụng list (islice (cycle (['b', 'r', 'g', 'y', 'k']), None, len (df)))).
vkontori 20/12/12

Cảm ơn, tôi có lẽ đã không hiểu được điều đó. Một tùy chọn khác là tạo chu trình trước, sau đó chỉ cần gọi nexthàm của nó bên trong phần hiểu.
ely 20/12/12

Đúng vậy. it = cycle (['b', 'r', 'g', 'y', 'k']); my_colors = [tiếp theo (nó) for i in xrange (LEN (df))] sẽ cắt nó cũng ...
vkontori

1
Với gấu trúc và matplotlib được cài đặt ngày hôm nay, mã trên không tạo ra gì cho tôi, mặc dù nó chạy.
kakyo

@kakyo Bạn đang chạy trong trình thông dịch thông thường, IPython hay từ shell (hoặc thứ gì khác)? Tùy thuộc vào loại môi trường bạn thực thi mã này bên trong, bạn có thể cần bật chế độ tương tác cho matplotlib hoặc đặt pylab.ion()cho pylab tương tác.
ely

52

Tôi thấy cách dễ nhất là sử dụng colormaptham số .plot()với một trong các màu chuyển sắc đặt trước:

df.plot(kind='bar', stacked=True, colormap='Paired')

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

Bạn có thể tìm thấy một danh sách lớn các bản đồ màu được thiết lập sẵn tại đây .

bản đồ màu


18
trong trường hợp của tôi, điều này chỉ mang lại một màu trên tất cả các thanh
tsando


15

Để có câu trả lời chi tiết hơn về cách tạo bản đồ màu của riêng bạn, tôi thực sự khuyên bạn nên truy cập trang này

Nếu câu trả lời đó là quá nhiều công việc, bạn có thể nhanh chóng tạo danh sách màu của riêng mình và chuyển chúng vào colortham số. Tất cả các bản đồ màu đều nằm trong cmmô-đun matplotlib. Hãy lấy danh sách 30 giá trị màu RGB (cộng với alpha) từ bản đồ màu địa ngục đảo ngược. Để làm như vậy, trước tiên hãy lấy bản đồ màu và sau đó chuyển cho nó một chuỗi các giá trị từ 0 đến 1. Ở đây, chúng tôi sử dụng np.linspaceđể tạo 30 giá trị cách đều nhau giữa .4 và .8 đại diện cho phần đó của bản đồ màu.

from matplotlib import cm
color = cm.inferno_r(np.linspace(.4, .8, 30))
color

array([[ 0.865006,  0.316822,  0.226055,  1.      ],
       [ 0.851384,  0.30226 ,  0.239636,  1.      ],
       [ 0.832299,  0.283913,  0.257383,  1.      ],
       [ 0.817341,  0.270954,  0.27039 ,  1.      ],
       [ 0.796607,  0.254728,  0.287264,  1.      ],
       [ 0.775059,  0.239667,  0.303526,  1.      ],
       [ 0.758422,  0.229097,  0.315266,  1.      ],
       [ 0.735683,  0.215906,  0.330245,  1.      ],
       .....

Sau đó, chúng tôi có thể sử dụng điều này để vẽ biểu đồ, sử dụng dữ liệu từ bài đăng gốc:

import random
x = [{i: random.randint(1, 5)} for i in range(30)]
df = pd.DataFrame(x)
df.plot(kind='bar', stacked=True, color=color, legend=False, figsize=(12, 4))

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


2
Đây là tài liệu về các bản đồ màu khác ngoài inferno_r: matplotlib.org/examples/color/colormaps_reference.html
tsando

1
Tôi đã làm theo đoạn mã này nhưng mảng màu của tôi luôn có các giá trị giống nhau.
FaCoffee
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.