ขนาดเครื่องหมายพล็อตกระจายของ pyplot


376

ในเอกสาร pyplot สำหรับพล็อตกระจาย:

matplotlib.pyplot.scatter(x, y, s=20, c='b', marker='o', cmap=None, norm=None,
                          vmin=None, vmax=None, alpha=None, linewidths=None,
                          faceted=True, verts=None, hold=None, **kwargs)

ขนาดเครื่องหมาย

s: ขนาดเป็นคะแนน ^ 2 มันเป็นสเกลาร์หรืออาร์เรย์ที่มีความยาวเท่ากันกับ x และ y

หน่วยประเภทpoints^2ใด มันหมายความว่าอะไร? ไม่s=100ได้หมายความว่า10 pixel x 10 pixel?

โดยทั่วไปฉันกำลังพยายามทำแผนการกระจายที่มีขนาดเครื่องหมายที่แตกต่างกันและฉันต้องการทราบว่าตัวเลขนั้นมีความsหมายว่าอย่างไร


ค่อนข้างแน่ใจว่าคะแนนเป็นหน่วยเดียวกับที่ใช้กับแบบอักษร
tacaswell

@tcaswell หมายความs=20ว่าขนาดเครื่องหมายเท่ากับfontsize=20ตัวอักษรหรือไม่?
LWZ

ไม่พื้นที่จะเป็น 20 คะแนน ^ 2 fontsize=20ตัวอักษรมีความสูง 20 แต้ม (หรือตัวอักษรอ้างอิงในแบบอักษรคือสูง 20 แต้ม)
tacaswell

23
matplotlib.pyplot.plot()มีmsพารามิเตอร์ ( markersize) เทียบเท่ากับmatplotlib.pyplot.scatter()พารามิเตอร์s( size) แค่เป็นตัวเตือน ..
niekas

@neikas ดูเหมือนว่าพวกเขาจะไม่ได้เพราะหนึ่งในพิกเซล (markersize) และอื่น ๆ ที่อยู่ในหน่วยจุดที่แปลกประหลาดนี้ขนาด (ขนาด) สิ่งนี้สร้างความสับสนให้ฉันมาตลอด แต่ฉันเชื่อว่ามันเกี่ยวข้องกับขนาดเครื่องหมายของ scatterplot ที่ใช้เพื่อแสดงจำนวนในลักษณะที่เป็นสัดส่วน
heltonbiker

คำตอบ:


406

นี่อาจเป็นวิธีที่ทำให้สับสนในการกำหนดขนาด แต่โดยทั่วไปคุณจะระบุพื้นที่ของเครื่องหมาย ซึ่งหมายความว่าหากต้องการเพิ่มความกว้างของเครื่องหมาย (หรือความสูง) เป็นสองเท่าคุณจะต้องเพิ่มsเป็น 4 เท่า [เนื่องจาก A = W H => (2W) (2H) = 4A]

อย่างไรก็ตามมีเหตุผลว่าขนาดของเครื่องหมายถูกกำหนดด้วยวิธีนี้ เนื่องจากขนาดของพื้นที่เป็นสแควร์ของความกว้างการเพิ่มความกว้างเป็นสองเท่าจริง ๆ แล้วเพิ่มขนาดมากกว่าปัจจัย 2 (ในความเป็นจริงมันเพิ่มขึ้นเป็น 4 เท่า) หากต้องการดูสิ่งนี้ให้พิจารณาสองตัวอย่างต่อไปนี้และเอาต์พุตที่สร้าง

# doubling the width of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*4**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

จะช่วยให้

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

สังเกตว่าขนาดเพิ่มขึ้นอย่างรวดเร็วมากแค่ไหน ถ้าเรามี

# doubling the area of markers
x = [0,2,4,6,8,10]
y = [0]*len(x)
s = [20*2**n for n in range(len(x))]
plt.scatter(x,y,s=s)
plt.show()

จะช่วยให้

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

ตอนนี้ขนาดที่ชัดเจนของเครื่องหมายเพิ่มขึ้นเป็นเส้นตรงในแบบที่เป็นธรรมชาติ

สำหรับความหมายที่แท้จริงของสิ่งที่ 'จุด' คือมันค่อนข้างมีกฎเกณฑ์สำหรับจุดประสงค์ในการวางแผนคุณเพียงแค่ปรับขนาดทั้งหมดของคุณด้วยค่าคงที่จนกว่าพวกเขาจะดูสมเหตุสมผล

หวังว่านี่จะช่วยได้!

แก้ไข: (ตอบกลับความคิดเห็นจาก @Emma)

มันอาจทำให้ถ้อยคำสับสนในส่วนของฉัน คำถามที่ถามเกี่ยวกับการเพิ่มความกว้างของวงกลมเป็นสองเท่าดังนั้นในภาพแรกสำหรับแต่ละวงกลม (ในขณะที่เราเลื่อนจากซ้ายไปขวา) ความกว้างนั้นเพิ่มเป็นสองเท่าของวงกลมก่อนหน้าดังนั้นสำหรับพื้นที่นี่คือเลขชี้กำลังกับฐาน 4 วงกลมแต่ละวงมีพื้นที่เป็นสองเท่าของวงกลมสุดท้ายซึ่งให้เลขชี้กำลังด้วยฐาน 2

อย่างไรก็ตามมันเป็นตัวอย่างที่สอง (ที่เราอยู่ในพื้นที่ปรับขนาด) พื้นที่ที่ปรากฏขึ้นสองเท่าเพื่อทำให้วงกลมใหญ่เป็นสองเท่าของดวงตา ดังนั้นถ้าเราต้องการให้วงกลมปรากฎตัวปัจจัยที่nใหญ่กว่าเราก็จะเพิ่มพื้นที่โดยปัจจัยที่nไม่ใช่รัศมีดังนั้นขนาดที่ปรากฏจะปรับขนาดเชิงเส้นตรงกับพื้นที่

แก้ไขเพื่อให้เห็นภาพความคิดเห็นโดย @TomaszGandor:

นี่คือสิ่งที่ดูเหมือนกับฟังก์ชั่นที่แตกต่างกันของขนาดเครื่องหมาย:

ขนาดเอ็กซ์โปเนนเชียลสแควร์หรือเชิงเส้น

x = [0,2,4,6,8,10,12,14,16,18]
s_exp = [20*2**n for n in range(len(x))]
s_square = [20*n**2 for n in range(len(x))]
s_linear = [20*n for n in range(len(x))]
plt.scatter(x,[1]*len(x),s=s_exp, label='$s=2^n$', lw=1)
plt.scatter(x,[0]*len(x),s=s_square, label='$s=n^2$')
plt.scatter(x,[-1]*len(x),s=s_linear, label='$s=n$')
plt.ylim(-1.5,1.5)
plt.legend(loc='center left', bbox_to_anchor=(1.1, 0.5), labelspacing=3)
plt.show()

2
ฉันอาจจะเข้าใจผิดจุดของคุณ แต่ในตัวอย่างที่สองของคุณคุณกำลังเพิ่ม s แทน (s = [20, 40, 80, 160, 320, 640]) และบอกว่านั่นทำให้เรามีขนาดเชิงเส้นดูดีขึ้น มันจะไม่สมเหตุสมผลถ้าการเพิ่มขนาดเป็นเส้นตรง (เช่น s = [20, 40, 60, 80, 100, 120]) ให้ผลลัพธ์เชิงเส้น
เอ็มม่า

@Emma ปรีชาของคุณถูกต้องมันเป็นถ้อยคำที่ไม่ดีในส่วนของฉัน ฉันอธิบายเพิ่มเติมในการแก้ไขเพราะมันยาวเกินไปสำหรับความคิดเห็น
ด่าน

1
เป็นไปได้หรือไม่ที่จะเปลี่ยนsค่าตามขนาดของหน้าต่างรูป? ฉันหมายความว่าถ้าเราเพิ่มขนาดหน้าต่างให้ใหญ่ที่สุดฉันต้องการให้มีขนาดที่ใหญ่กว่า
Sigur

2
ตัวอย่างที่ดี (สิ่งที่จำเป็น!) นี้ไม่ควรจะเป็น4 ** nและ2 ** nแต่และn ** 4 n ** 2ด้วย2 ** nพล็อตที่สองไม่ได้ปรับขนาดเชิงเส้นในแง่ของเส้นผ่าศูนย์กลางวงกลม มันยังเร็วเกินไป (ไม่มากไปกว่านั้น)
Tomasz Gandor

1
หากต้องการทำให้สั้นลง - พล็อตที่สองแสดงรากที่สองของเลขชี้กำลัง - ซึ่งเป็นเลขยกกำลังอื่นซึ่งสูงชันน้อยกว่าเล็กน้อย
Tomasz Gandor

218

เนื่องจากคำตอบอื่น ๆ ที่นี่อ้างว่าsแสดงถึงพื้นที่ของเครื่องหมายฉันจึงเพิ่มคำตอบนี้เพื่อชี้แจงว่าไม่จำเป็นต้องเป็นกรณีนี้

ขนาดเป็นคะแนน ^ 2

อาร์กิวเมนต์sในซึกplt.scatter markersize**2ตามที่เอกสารระบุไว้

s: scalar หรือ array_like, รูปร่าง (n,),
ขนาดเสริมในหน่วยคะแนน ^ 2 ค่าเริ่มต้นคือ rcParams ['lines.markersize'] ** 2

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

ดังนั้นความสัมพันธ์ระหว่างเครื่องหมายของพล็อตบรรทัดและอาร์กิวเมนต์ขนาดการกระจายคือสี่เหลี่ยม เพื่อผลิตเครื่องหมายกระจายขนาดเดียวกันเป็นเครื่องหมายพล็อตขนาด 10 scatter( .., s=100)คะแนนคุณจึงจะเรียก

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

import matplotlib.pyplot as plt

fig,ax = plt.subplots()

ax.plot([0],[0], marker="o",  markersize=10)
ax.plot([0.07,0.93],[0,0],    linewidth=10)
ax.scatter([1],[0],           s=100)

ax.plot([0],[1], marker="o",  markersize=22)
ax.plot([0.14,0.86],[1,1],    linewidth=22)
ax.scatter([1],[1],           s=22**2)

plt.show()

การเชื่อมต่อกับ "พื้นที่"

เหตุใดจึงต้องมีคำตอบอื่น ๆ และแม้แต่เอกสารอธิบายเกี่ยวกับ "พื้นที่" เมื่อพูดถึงsพารามิเตอร์

แน่นอนหน่วยคะแนน ** 2 เป็นหน่วยพื้นที่

  • สำหรับกรณีพิเศษของเครื่องหมายสี่เหลี่ยมจัตุรัสmarker="s"พื้นที่ของเครื่องหมายแน่นอนโดยตรงกับค่าของsพารามิเตอร์
  • area = pi/4*sสำหรับแวดวงพื้นที่ของวงกลมคือ
  • สำหรับเครื่องหมายอื่น ๆ อาจไม่มีความสัมพันธ์ใด ๆ ที่ชัดเจนกับพื้นที่ของเครื่องหมาย

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

ในทุกกรณี แต่พื้นที่ของเครื่องหมายที่เป็นสัดส่วนกับsพารามิเตอร์ นี่คือแรงจูงใจที่จะเรียกมันว่า "พื้นที่" แม้ว่าในกรณีส่วนใหญ่มันไม่ได้เป็นจริง

การระบุขนาดของเครื่องหมายการกระจายในแง่ของปริมาณซึ่งเป็นสัดส่วนกับพื้นที่ของเครื่องหมายที่ทำให้ในความหมายที่เป็นพื้นที่ของเครื่องหมายที่รับรู้เมื่อเปรียบเทียบแพทช์ที่แตกต่างกันมากกว่าความยาวด้านหรือเส้นผ่าศูนย์กลาง นั่นคือการเพิ่มปริมาณพื้นฐานเป็นสองเท่าควรเพิ่มพื้นที่ของเครื่องหมาย

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

คะแนนคืออะไร

จนถึงตอนนี้คำตอบของขนาดเครื่องหมายของการกระจายหมายถึงการให้ในหน่วยของคะแนน คะแนนมักจะใช้ในการพิมพ์ที่มีการระบุแบบอักษรในจุด นอกจากนี้ยังมีการระบุ linewidths เป็นจุด ขนาดมาตรฐานของคะแนนใน matplotlib คือ 72 คะแนนต่อนิ้ว (ppi) - 1 จุดจึงเท่ากับ 1/72 นิ้ว

อาจมีประโยชน์ในการระบุขนาดเป็นพิกเซลแทนคะแนน หากตัวเลข dpi เป็น 72 เช่นกันจุดหนึ่งคือหนึ่งพิกเซล หากตัวเลข dpi แตกต่าง (ค่าเริ่มต้นของ matplotlib คือfig.dpi=100)

1 point == fig.dpi/72. pixels

ในขณะที่ขนาดของตัวทำเครื่องหมายกระจายในคะแนนจะดูแตกต่างกันสำหรับรูป dpi ที่แตกต่างกัน แต่สามารถสร้างเครื่องหมาย 10 x 10 พิกเซล ^ 2 ซึ่งมักจะมีจำนวนพิกเซลที่ครอบคลุมอยู่เสมอ:

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

import matplotlib.pyplot as plt

for dpi in [72,100,144]:

    fig,ax = plt.subplots(figsize=(1.5,2), dpi=dpi)
    ax.set_title("fig.dpi={}".format(dpi))

    ax.set_ylim(-3,3)
    ax.set_xlim(-2,2)

    ax.scatter([0],[1], s=10**2, 
               marker="s", linewidth=0, label="100 points^2")
    ax.scatter([1],[1], s=(10*72./fig.dpi)**2, 
               marker="s", linewidth=0, label="100 pixels^2")

    ax.legend(loc=8,framealpha=1, fontsize=8)

    fig.savefig("fig{}.png".format(dpi), bbox_inches="tight")

plt.show() 

หากคุณสนใจที่จะกระจายข้อมูลหน่วยตรวจสอบคำตอบนี้


สงสัยว่าใครจะคำนวณว่าพารามิเตอร์ s ใดมอบให้กับการกระจายเพื่อให้ได้วงกลมซึ่งครอบคลุมเส้นผ่านศูนย์กลางของสมมุติว่า 0.1 ในพิกัดที่แท้จริงของพล็อต (เพื่อเติมช่องว่างระหว่างสมมุติ 0.4 และ 0.5 บนพล็อตจาก (0 , 0) ถึง (1,1)?
Anatoly Alekseev

@AnatolyAlekseev ที่ควรจะได้รับคำตอบจากนี้คำถาม
ImportanceOfBeingErnest

21

คุณสามารถใช้markersizeเพื่อระบุขนาดของวงกลมในวิธีการลงจุด

import numpy as np
import matplotlib.pyplot as plt

x1 = np.random.randn(20)
x2 = np.random.randn(20)
plt.figure(1)
# you can specify the marker size two ways directly:
plt.plot(x1, 'bo', markersize=20)  # blue circle with size 10 
plt.plot(x2, 'ro', ms=10,)  # ms is just an alias for markersize
plt.show()

จากที่นี่

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


คำถามคือเกี่ยวกับ scatterplot และใน matplotlib ทั้งสองฟังก์ชั่นการวางแผนมีพารามิเตอร์ที่แตกต่างกัน ( markersizeสำหรับplotและsสำหรับscatter ) ดังนั้นคำตอบนี้ใช้ไม่ได้
Dom

3
@ ฉันลงคะแนนเพราะคำถามนี้ปรากฏขึ้นเป็นผลลัพธ์ครั้งแรกใน Google แม้ว่าฉันจะค้นหา "ขนาดเครื่องหมายพล็อตของ pyplot" ดังนั้นคำตอบนี้จะช่วยได้
Przemek D

ฉันรู้ว่าวิธีการแปลงและวิธีการกระจายแตกต่างกันใน PLT แต่พวกเขาทั้งสองสามารถรับรู้ว่า 'แผนการกระจาย' และปรับเครื่องหมายดังนั้นคำตอบนี้เป็นอีกวิธีหนึ่งถ้าคุณใช้วิธีการพล็อต @Dom
zhaoqing

18

มันคือพื้นที่ของเครื่องหมาย ผมหมายถึงถ้าคุณมีs1 = 1000แล้วความสัมพันธ์ระหว่างรัศมีของวงกลมแต่ละคือ:s2 = 4000 r_s2 = 2 * r_s1ดูพล็อตต่อไปนี้:

plt.scatter(2, 1, s=4000, c='r')
plt.scatter(2, 1, s=1000 ,c='b')
plt.scatter(2, 1, s=10, c='g')

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

ฉันมีข้อสงสัยเหมือนกันเมื่อฉันเห็นโพสต์ดังนั้นฉันจึงทำตัวอย่างนี้จากนั้นฉันใช้ไม้บรรทัดบนหน้าจอเพื่อวัดรัศมี


นี่เป็นคำตอบที่สะอาดและไร้ไขมันมากที่สุด ขอบคุณ
Ayan Mitra

6

ฉันพยายามใช้ 'กระจาย' เริ่มแรกเพื่อจุดประสงค์นี้ หลังจากเสียเวลาเล็กน้อย - ฉันตัดสินตามวิธีแก้ปัญหาต่อไปนี้

import matplotlib.pyplot as plt
input_list = [{'x':100,'y':200,'radius':50, 'color':(0.1,0.2,0.3)}]    
output_list = []   
for point in input_list:
    output_list.append(plt.Circle((point['x'], point['y']), point['radius'], color=point['color'], fill=False))
ax = plt.gca(aspect='equal')
ax.cla()
ax.set_xlim((0, 1000))
ax.set_ylim((0, 1000))
for circle in output_list:    
   ax.add_artist(circle)

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

นี่คือคำตอบของ คำถามนี้


มีประโยชน์มาก แต่ทำไมใช้สองลูป
grabantot

1
@grantantot ไม่มีเหตุผลเพียงแค่ไม่ได้คิดมากเกินไป
Ike

2

หากขนาดของวงกลมสอดคล้องกับสแควร์ของพารามิเตอร์s=parameterให้กำหนดสแควร์รูทให้กับแต่ละองค์ประกอบที่คุณผนวกเข้ากับอาร์เรย์ขนาดของคุณเช่นนี้s=[1, 1.414, 1.73, 2.0, 2.24]เช่นเมื่อมันรับค่าเหล่านี้และส่งกลับพวกมันการเพิ่มขนาดสัมพัทธ์ของพวกมัน สแควร์รูทของความก้าวหน้ากำลังสองซึ่งส่งกลับความก้าวหน้าเชิงเส้น

output=[1, 2, 3, 4, 5]ถ้าฉันเป็นตารางแต่ละคนที่จะได้รับออกไปพล็อต: ลองตีความรายการ:s=[numpy.sqrt(i) for i in s]


1
ควรจะi in outputไม่ควร?
Sigur
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.