กำหนดขนาดของแถบสี Matplotlib ให้ตรงกับกราฟ


161

ฉันไม่สามารถใช้ colorbar บนกราฟแสดงผลแบบนี้ให้สูงเท่ากับกราฟได้เพราะใช้ Photoshop ไม่ได้ ฉันจะทำให้ความสูงให้ตรงกันได้อย่างไรตัวอย่างขนาด colorbar ที่ไม่ตรงกัน


คุณเคยลองใช้คำแนะนำจากstackoverflow.com/questions/16702479/ หรือไม่
lmjohns3

@ imjohns3 ไม่มีอะไรในโพสต์ที่ดูเหมือนว่าจะทำอะไรกับแถบสี มันมีขนาดเท่าเดิมไม่ว่าฉันจะตั้งค่าอะไร ถ้าฉันตั้งค่าเศษส่วนและลดขนาดของกราฟจะเปลี่ยนในขณะที่แถบสียังคงเหมือนเดิมจนกว่าเราจะกลับไปที่สิ่งที่ฉันมีอยู่แล้วพวกเขาก็หยุดทำอะไร
เอลเลียต

ตรวจสอบเอกสาร - matplotlib.org/api/colorbar_api.html - และใช้fractionหรือshrinkargs
BoltzmannBrain

คำตอบ:


194

คุณสามารถทำเช่นนี้ได้อย่างง่ายดายด้วย matplotlib AxisDivider

ตัวอย่างจากหน้าที่เชื่อมโยงใช้งานได้โดยไม่ต้องใช้ subplots:

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np

plt.figure()
ax = plt.gca()
im = ax.imshow(np.arange(100).reshape((10,10)))

# create an axes on the right side of ax. The width of cax will be 5%
# of ax and the padding between cax and ax will be fixed at 0.05 inch.
divider = make_axes_locatable(ax)
cax = divider.append_axes("right", size="5%", pad=0.05)

plt.colorbar(im, cax=cax)

ป้อนคำอธิบายรูปภาพที่นี่


1
ฉันไม่ได้ทำงานในแผนย่อยดังนั้นจึงไม่สามารถใช้ได้
เอลเลียต

หลังจากซ่อมเสร็จแล้วให้ทำงาน มีปัญหามากมายในการโต้ตอบกับ subplot_adjust คุณต้องรับสายในสถานที่ที่เหมาะสมซึ่งสัมพันธ์กัน
เอลเลียต

11
นี่เป็นการเปลี่ยนขนาดของกราฟเล็กน้อย ฉันมี 4 ในตาราง 2x2 แต่ต้องการเพียงสองทางด้านขวาเท่านั้นที่จะมีแท่ง (มาตราส่วนจะใช้ตามแถว) อย่างไรก็ตามสิ่งนี้ทำให้ขนาดไม่เท่ากัน ฉันพยายามเพียงแค่ไม่มีการเรียก colorbar (ด้วยการเรียกตัวแบ่ง) แต่แน่นอนว่านี่จะทำให้มีกล่องสีขาวและตัวเลขอยู่ด้านข้าง ฉันจะให้พวกเขามีขนาดที่สอดคล้องกันได้อย่างไร
เอลเลียต

@batatron โชคไม่ดีที่มันไม่สามารถใช้ได้กับแกนที่ฉาย
Bogdan

หากคุณต้องการที่จะเพิ่มชื่อโดยใช้plt.titleมันจะถูกแสดง swaped ไปทางขวา มีวิธีที่จะเอาชนะสิ่งนี้หรือไม่?
2820579

224

ชุดค่าผสมนี้ (และค่าใกล้เคียงกับค่าเหล่านี้) ดูเหมือนว่า "น่าอัศจรรย์" ใช้งานได้สำหรับฉันในการปรับขนาดของแถบสีให้อยู่ในพล็อตไม่ว่าจะแสดงผลในขนาดใดก็ตาม

plt.colorbar(im,fraction=0.046, pad=0.04)

นอกจากนี้ยังไม่จำเป็นต้องแชร์แกนที่สามารถพล็อตออกจากตาราง


4
สิ่งนี้อาจใช้งานได้ในบางกรณี แต่โดยทั่วไปแล้วมันไม่ทำงาน ลองเช่นการพล็อตเรื่องในคำถามเดิมที่มีความกว้างสองเท่าของความสูง
Matthias

ตัวเลือกเศษส่วนยังคงใช้งานได้ในกรณีที่คุณพูดถึงถ้าปรับให้ตรงกับความสูงของพล็อต (mpl v1.4.3)
skytaker

6
นี่เป็นวิธีที่เป็นสากลเพียงอย่างเดียวของการทำมัน โซลูชันที่มี axex_grid1 จะไม่ทำงานสำหรับแกนที่คาดการณ์เช่น GeoAxes
Bogdan

OMG มันยอดเยี่ยมมาก ขอบคุณมากสำหรับการแก้ปัญหา
2D_

3
ในการตอบกลับความคิดเห็น @Matthias คุณสามารถแก้ไขในกรณีที่ภาพกว้างเกินไปโดยใช้เคล็ดลับนี้: ภาพของคุณอยู่im_ratio = data.shape[0]/data.shape[1] plt.colorbar(im,fraction=0.046*im_ratio, pad=0.04)ที่ไหน data
eindzl

30

@batatron ได้ให้คำตอบที่แนะนำโดยmatplotlib docsซึ่งสร้างความสูงที่เหมาะสม แต่มันแนะนำปัญหาที่แตกต่าง ตอนนี้ความกว้างของ colorbar (เช่นเดียวกับช่องว่างระหว่าง colorbar และพล็อต) การเปลี่ยนแปลงด้วยความกว้างของพล็อต กล่าวอีกนัยหนึ่งอัตราส่วนของแถบสีจะไม่คงที่อีกต่อไป

เพื่อให้ได้ความสูงที่เหมาะสมและอัตราส่วนที่กำหนดคุณต้องขุดลึกลงไปในaxes_grid1โมดูลลึกลับ

import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import make_axes_locatable, axes_size
import numpy as np

aspect = 20
pad_fraction = 0.5

ax = plt.gca()
im = ax.imshow(np.arange(200).reshape((20, 10)))
divider = make_axes_locatable(ax)
width = axes_size.AxesY(ax, aspect=1./aspect)
pad = axes_size.Fraction(pad_fraction, width)
cax = divider.append_axes("right", size=width, pad=pad)
plt.colorbar(im, cax=cax)

โปรดทราบว่าสิ่งนี้ระบุความกว้างของ colorbar wrt ความสูงของพล็อต (ตรงกันข้ามกับความกว้างของรูปเหมือนก่อนหน้านี้)

ตอนนี้สามารถระบุระยะห่างระหว่าง colorbar และพล็อตเป็นเศษส่วนของความกว้างของ colorbar ซึ่งเป็น IMHO จำนวนที่มีความหมายมากกว่าเศษส่วนของความกว้างของรูป

พล็อตภาพที่มีแถบสี

UPDATE:

ฉันสร้างสมุดบันทึก IPython ในหัวข้อที่ฉันบรรจุโค้ดข้างต้นลงในฟังก์ชั่นที่ใช้งานได้ง่าย:

import matplotlib.pyplot as plt
from mpl_toolkits import axes_grid1

def add_colorbar(im, aspect=20, pad_fraction=0.5, **kwargs):
    """Add a vertical color bar to an image plot."""
    divider = axes_grid1.make_axes_locatable(im.axes)
    width = axes_grid1.axes_size.AxesY(im.axes, aspect=1./aspect)
    pad = axes_grid1.axes_size.Fraction(pad_fraction, width)
    current_ax = plt.gca()
    cax = divider.append_axes("right", size=width, pad=pad)
    plt.sca(current_ax)
    return im.axes.figure.colorbar(im, cax=cax, **kwargs)

มันสามารถใช้เช่นนี้:

im = plt.imshow(np.arange(200).reshape((20, 10)))
add_colorbar(im)

1
นี่เป็นฟังก์ชั่นเล็ก ๆ น้อย ๆ ที่เป็นประโยชน์จริงๆ! คำเตือนหนึ่งคำคือมันไม่ทำงานเมื่อคุณต้องการเพิ่มแถบสีหลายแถบเนื่องจากแถบสีจะปรากฏที่ด้านบนของอีกด้าน
David Hall

22

ฉันขอขอบคุณคำตอบทั้งหมดข้างต้น แต่ชอบคำตอบบางอย่างและความเห็นชี้ออกaxes_grid1โมดูลไม่สามารถ GeoAxes อยู่ในขณะที่การปรับfraction, pad, shrinkและพารามิเตอร์อื่น ๆ ที่คล้ายกันสามารถไม่จำเป็นต้องให้การสั่งซื้อที่แม่นยำมากซึ่งจริงๆรบกวนจิตใจผม ฉันเชื่อว่าการให้colorbarของตัวเองaxesอาจเป็นวิธีที่ดีกว่าในการแก้ไขปัญหาทั้งหมดที่กล่าวถึง

รหัส

import matplotlib.pyplot as plt
import numpy as np

fig=plt.figure()
ax = plt.axes()
im = ax.imshow(np.arange(100).reshape((10,10)))

# Create an axes for colorbar. The position of the axes is calculated based on the position of ax.
# You can change 0.01 to adjust the distance between the main image and the colorbar.
# You can change 0.02 to adjust the width of the colorbar.
# This practice is universal for both subplots and GeoAxes.

cax = fig.add_axes([ax.get_position().x1+0.01,ax.get_position().y0,0.02,ax.get_position().height])
plt.colorbar(im, cax=cax) # Similar to fig.colorbar(im, cax = cax)

ผลลัพธ์

ป้อนคำอธิบายรูปภาพที่นี่

ในภายหลังฉันพบmatplotlib.pyplot.colorbarเอกสารอย่างเป็นทางการแล้วยังมีaxตัวเลือกซึ่งเป็นแกนที่มีอยู่ที่จะให้ห้องสำหรับแถบสี ดังนั้นจึงมีประโยชน์สำหรับหลาย ๆ subplots ดูต่อไปนี้

รหัส

fig, ax = plt.subplots(2,1,figsize=(12,8)) # Caution, figsize will also influence positions.
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
fig.colorbar(im1, ax=ax)

ผลลัพธ์

ป้อนคำอธิบายรูปภาพที่นี่

อีกครั้งคุณสามารถบรรลุผลที่คล้ายกันโดยระบุ cax วิธีที่แม่นยำยิ่งขึ้นจากมุมมองของฉัน

รหัส

fig, ax = plt.subplots(2,1,figsize=(12,8))
im1 = ax[0].imshow(np.arange(100).reshape((10,10)), vmin = -100, vmax =100)
im2 = ax[1].imshow(np.arange(-100,0).reshape((10,10)), vmin = -100, vmax =100)
cax = fig.add_axes([ax[1].get_position().x1-0.25,ax[1].get_position().y0,0.02,ax[0].get_position().y1-ax[1].get_position().y0])
fig.colorbar(im1, cax=cax)

ผลลัพธ์

ป้อนคำอธิบายรูปภาพที่นี่


@ HS-nebula ขอบคุณสำหรับความคิดเห็นของคุณและฉันดีใจที่คุณสนุกกับมัน :)
Fei Yao

คำตอบที่น่าทึ่งจริงๆ ขอบคุณ!!
ตอนที่

11

เมื่อคุณสร้างความcolorbarพยายามโดยใช้พารามิเตอร์เศษส่วนและ / หรือการย่อขนาด

จากเอกสาร:

ส่วน 0.15; เศษส่วนของแกนดั้งเดิมที่จะใช้สำหรับแถบสี

หดตัว 1.0; เศษส่วนที่จะทำให้แถบสีหด


1
ถ้าฉันตั้งค่าการย่อขนาด 1.0 และเศษส่วนให้กับสิ่งใด ๆ มันจะลดขนาดกราฟโดยไม่มีผลกระทบกับขนาดของแถบสีเลยจนกว่าการเปลี่ยนเศษส่วนจะทำให้มันเป็นสิ่งที่ฉันมีอยู่แล้ว
Elliot

คุณจะระบุได้อย่างแม่นยำว่าพวกเขาจะต้องเป็นพารามิเตอร์ของcolorbar()ฟังก์ชั่นหรือวิธีการ
Steve Barnes

ขอบคุณ เพียงแค่ต้องระบุพารามิเตอร์การหดตัวและมันก็ใช้งานได้เหมือนเวทมนตร์!
CodingNow

11

วิธีแก้ปัญหาทั้งหมดข้างต้นนั้นดี แต่ฉันชอบ @ Steve's และ @ bejota ที่สุดเท่าที่จะทำได้เพราะพวกเขาไม่ได้เกี่ยวข้องกับการโทรแฟนซีและเป็นสากล

โดยทั่วไปผมหมายถึงงานที่มีประเภทใด ๆ GeoAxesของแกนรวมทั้ง ตัวอย่างเช่นคุณมีแกนที่ฉายสำหรับการทำแผนที่:

projection = cartopy.crs.UTM(zone='17N')
ax = plt.axes(projection=projection)
im = ax.imshow(np.arange(200).reshape((20, 10)))

โทรไปที่

cax = divider.append_axes("right", size=width, pad=pad)

จะล้มเหลวด้วย: KeyException: map_projection

ดังนั้นวิธีสากลในการจัดการขนาดแถบสีกับแกนทุกประเภทคือ:

ax.colorbar(im, fraction=0.046, pad=0.04)

ทำงานกับเศษส่วนจาก 0.035 ถึง 0.046 เพื่อให้ได้ขนาดที่ดีที่สุดของคุณ อย่างไรก็ตามค่าสำหรับเศษส่วนและ paddig จะต้องมีการปรับเพื่อให้ได้ขนาดที่เหมาะสมที่สุดสำหรับพล็อตของคุณและจะแตกต่างกันไปขึ้นอยู่กับการวางแนวของแถบสีในแนวตั้งหรือแนวนอน


1
เรายังสามารถเพิ่มshrinkพารามิเตอร์เมื่อfractionพร้อมกับpadไม่ให้ผลลัพธ์ที่ต้องการเพียงพอ
Fei Yao
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.