Pandalar / matplotlib çubuk grafiği özel renkleri nasıl verilir


86

Yığılmış çubuk grafikler oluşturmak için Excel'in yerine panda / matplotlib kullanmaya başladım. Bir sorunla karşılaşıyorum

(1) Varsayılan renk haritasında yalnızca 5 renk vardır, bu nedenle 5'ten fazla kategorim varsa renkler tekrar eder. Nasıl daha fazla renk belirleyebilirim? İdeal olarak, bir başlangıç ​​rengi ve bir bitiş rengi olan bir gradyan ve aralarında dinamik olarak n renk oluşturmanın bir yolu?

(2) renkler görsel olarak pek hoş değil. Özel bir n renk setini nasıl belirtebilirim? Veya bir gradyan da işe yarar.

Yukarıdaki noktaların her ikisini de gösteren bir örnek aşağıdadır:

  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)

Ve çıktı şudur:

görüntü açıklamasını buraya girin


Kısmi bir renk haritası almanın oldukça kolay bir yolu var. Aşağıdaki bu çözüme bakın
Ted Petrou

Yanıtlar:


120

colorSeçeneği doğrudan plotişleve bir liste olarak belirtebilirsiniz .

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)

Kendi özel listenizi tanımlamak için, aşağıdakilerden birkaçını yapabilir veya bir renk öğesini RGB değerlerine göre tanımlamak için Matplotlib tekniklerine bakabilirsiniz. Bununla istediğiniz kadar karmaşıklaşabilirsiniz.

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.

Son örnek, benim için aşağıdaki basit renk geçişini veriyor:

görüntü açıklamasını buraya girin

Efsaneyi tanımlanmış renkleri almaya nasıl zorlayacağımı anlayacak kadar uzun süre oynamadım ama eminim yapabilirsin.

Genel olarak, yine de, büyük bir tavsiye sadece Matplotlib'deki işlevleri doğrudan kullanmaktır. Onları Pandas'tan aramak sorun değil, ancak onları doğrudan Matplotlib'den çağırarak daha iyi seçenekler ve performans elde ettiğinizi görüyorum.


3
Küçük hata: my_colors = [döngüsü (['b', 'r', 'g', 'y', 'k']). Next () aralıktaki i için (len (df))] 'b' verecektir python 2.7'de her zaman. Bunun yerine list (islice (döngü (['b', 'r', 'g', 'y', 'k']), Hiçbiri, len (df))) kullanmalısınız.
vkontori

Teşekkürler, muhtemelen bunu anlayamazdım. Diğer bir seçenek de önce döngüyü oluşturmak, ardından sadece nextanlama içindeki işlevini çağırmaktır .
ely

Evet. it = döngüsü (['b', 'r', 'g', 'y', 'k']); my_colors = [xrange'de i için sonraki (it) (len (df))] onu da keser ...
vkontori

1
Bugün kurulu pandalar ve matplotlib ile, yukarıdaki kod çalışmasına rağmen benim için hiçbir şey üretmiyor.
kakyo

@kakyo Normal yorumlayıcıda, IPython'da mı yoksa kabuktan mı (veya başka bir şeyden) mı çalışıyorsunuz? Bu kodu hangi ortamda çalıştırdığınıza bağlı olarak, matplotlib için etkileşimli modu pylab.ion()açmanız veya etkileşimli pilab için ayarlamanız gerekebilir.
ely


15

Kendi renk haritalarınızı oluşturmayla ilgili daha ayrıntılı bir yanıt için, bu sayfayı ziyaret etmenizi önemle tavsiye ederim.

Bu cevap çok fazla çalışıyorsa, hızlı bir şekilde kendi renk listenizi oluşturabilir ve bunları colorparametreye geçirebilirsiniz . Tüm renk haritaları cmmatplotlib modülündedir. Tersine çevrilmiş inferno renk haritasından 30 RGB (artı alfa) renk değerinin bir listesini alalım. Bunu yapmak için, önce renk haritasını alın ve ardından 0 ile 1 arasında bir değer dizisi geçirin. Burada, np.linspacerenk haritasının o bölümünü temsil eden .4 ile .8 arasında eşit aralıklı 30 değer oluşturmak için kullanırız .

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.      ],
       .....

Ardından, orijinal gönderideki verileri kullanarak bunu planlamak için kullanabiliriz:

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

görüntü açıklamasını buraya girin


2
İşte diğer renge belgeler dışında haritaları var inferno_r: matplotlib.org/examples/color/colormaps_reference.html
tsando

1
Bu parçacığı takip ettim ama renk dizim her zaman aynı değerlere sahip.
FaCoffee
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.