ukuran penanda plot sebaran pyplot

376

Dalam dokumen pyplot untuk sebar plot:

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)

Ukuran marker

s: ukuran dalam poin ^ 2. Ini adalah skalar atau array dengan panjang yang sama dengan x dan y.

Unit apa itu points^2? Apa artinya? Apakah s=100artinya10 pixel x 10 pixel ?

Pada dasarnya saya mencoba membuat plot pencar dengan ukuran penanda yang berbeda, dan saya ingin mencari tahu apa arti sangka tersebut.

LWZ
sumber
cukup yakin bahwa poin adalah satuan yang sama yang digunakan untuk font.
tacaswell
@tcaswell, maksud Anda berarti s=20ukuran marker sama dengan fontsize=20huruf?
LWZ
tidak, area akan menjadi 20 poin ^ 2, fontsize=20huruf setinggi 20 pts (atau apa pun karakter referensi dalam font adalah 20 pts tinggi).
tacaswell
23
matplotlib.pyplot.plot()memiliki msparameter ( markersize) setara dengan matplotlib.pyplot.scatter()parameter s( size). Hanya pengingat ..
niekas
@neikas menurut saya mereka tidak, karena satu dalam piksel (markersize) dan lainnya dalam unit poin kuadrat aneh (ukuran). Ini selalu membingungkan saya, tetapi saya percaya itu ada hubungannya dengan ukuran marker scatterplot yang digunakan untuk menunjukkan jumlah dengan cara yang proporsional secara visual.
heltonbiker

Jawaban:

406

Ini bisa menjadi cara yang agak membingungkan untuk menentukan ukuran tetapi pada dasarnya Anda menentukan area marker. Ini berarti, untuk menggandakan lebar (atau tinggi) marker, Anda perlu menambah sdengan faktor 4. [karena A = W H => (2W) (2H) = 4A]

Namun, ada alasan bahwa ukuran marker didefinisikan dengan cara ini. Karena penskalaan area sebagai kuadrat lebar, menggandakan lebar sebenarnya tampak meningkatkan ukuran lebih dari satu faktor 2 (pada kenyataannya ia meningkatkannya dengan faktor 4). Untuk melihat ini perhatikan dua contoh berikut dan output yang mereka hasilkan.

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

memberi

masukkan deskripsi gambar di sini

Perhatikan bagaimana ukurannya meningkat dengan sangat cepat. Jika sebaliknya kita miliki

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

memberi

masukkan deskripsi gambar di sini

Sekarang ukuran jelas dari penanda meningkat secara linear secara intuitif.

Adapun makna yang tepat dari apa 'titik' itu, cukup sewenang-wenang untuk merencanakan tujuan, Anda hanya dapat skala semua ukuran Anda dengan konstanta sampai mereka terlihat masuk akal.

Semoga ini membantu!

Edit: (Menanggapi komentar dari @Emma)

Mungkin kata-kata yang membingungkan di pihak saya. Pertanyaan yang diajukan tentang menggandakan lebar lingkaran sehingga pada gambar pertama untuk setiap lingkaran (saat kami bergerak dari kiri ke kanan) lebarnya dua kali lipat sehingga untuk area ini adalah eksponensial dengan basis 4. Demikian pula contoh kedua setiap lingkaran memiliki luas dua kali lipat yang terakhir yang memberikan eksponensial dengan basis 2.

Namun itu adalah contoh kedua (di mana kita adalah area penskalaan) bahwa area penggandaan tampaknya membuat lingkaran dua kali lebih besar bagi mata. Jadi jika kita ingin sebuah lingkaran muncul faktor yang nlebih besar kita akan menambah luas dengan faktor nbukan jari-jari sehingga ukuran yang terlihat berskala linier dengan area tersebut.

Edit untuk memvisualisasikan komentar oleh @TomaszGandor:

Ini seperti apa fungsi yang berbeda dari ukuran marker:

Ukuran eksponensial, Kuadrat, atau Linear

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()
Dan
sumber
2
Saya mungkin salah paham maksud Anda, tetapi dalam contoh kedua Anda, Anda meningkatkan s secara eksponensial (s = [20, 40, 80, 160, 320, 640]) dan mengatakan bahwa itu memberi kami peningkatan ukuran yang tampak linier. Bukankah lebih masuk akal jika meningkatkan ukuran secara linear (mis. S = [20, 40, 60, 80, 100, 120]) memberi kami hasil yang tampak linier?
Emma
@ Emma Intuisi Anda benar, itu kata-kata yang buruk di pihak saya (alternatif pilihan penskalaan sumbu x). Saya menjelaskan beberapa hal lagi dalam sebuah pengeditan karena terlalu panjang untuk berkomentar.
Dan
1
Apakah mungkin untuk mengubah snilai sesuai dengan ukuran jendela gambar? Maksud saya, jika kita memaksimalkan angka windows, saya ingin memiliki tanda ukuran yang lebih besar.
Sigur
2
Contoh yang bagus (hanya hal-hal yang diperlukan!). Seharusnya tidak 4 ** ndan 2 ** n, tapi n ** 4dan n ** 2. Dengan 2 ** nplot kedua tidak skala secara linear dalam hal diameter lingkaran. Itu masih berjalan terlalu cepat (hanya saja tidak terlalu banyak di atas).
Tomasz Gandor
1
Singkatnya - plot kedua menunjukkan akar kuadrat dari eksponensial - yang merupakan eksponensial lain, hanya sedikit kurang curam.
Tomasz Gandor
218

Karena jawaban lain di sini mengklaim yang smenunjukkan area penanda, saya menambahkan jawaban ini untuk menjelaskan bahwa ini tidak selalu demikian.

Ukuran dalam poin ^ 2

Argumen sdalam plt.scattermenunjukkan markersize**2. Seperti yang dikatakan dalam dokumentasi

s: skalar atau array_like, bentuk (n,),
ukuran opsional dalam poin ^ 2. Defaultnya adalah rcParams ['lines.markersize'] ** 2.

Ini dapat dipahami secara harfiah. Untuk mendapatkan marker yang x poin besar, Anda harus menguadratkan angka itu dan memberikannya pada sargumen.

Jadi hubungan antara penanda garis plot dan argumen ukuran sebaran adalah kuadrat. Untuk menghasilkan penanda sebar dengan ukuran yang sama dengan penanda plot dengan ukuran 10 poin maka Anda akan menelepon scatter( .., s=100).

masukkan deskripsi gambar di sini

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

Koneksi ke "area"

Jadi mengapa jawaban lain dan bahkan dokumentasi berbicara tentang "area" ketika datang ke sparameter?

Tentu saja satuan poin ** 2 adalah satuan luas.

  • Untuk kasus khusus marker persegi marker="s", luas marker memang langsung nilais parameter.
  • Untuk lingkaran, luas lingkaran adalah area = pi/4*s.
  • Untuk marker lain mungkin tidak ada hubungan yang jelas dengan area marker.

masukkan deskripsi gambar di sini

Namun dalam semua kasus luas penanda sebanding dengan sparameter . Ini adalah motivasi untuk menyebutnya "area" walaupun dalam banyak kasus sebenarnya tidak.

Menentukan ukuran marker pencar dalam hal jumlah yang sebanding dengan luas marker membuatnya sejauh ini masuk akal karena merupakan area marker yang dirasakan ketika membandingkan tambalan yang berbeda daripada panjang sisi atau diameternya. Yaitu menggandakan kuantitas yang mendasari harus menggandakan area marker.

masukkan deskripsi gambar di sini

Apa poinnya?

Sejauh ini jawaban untuk apa arti ukuran sebar marker diberikan dalam satuan poin. Poin sering digunakan dalam tipografi, di mana font ditentukan dalam poin. Linewidths juga sering ditentukan dalam poin. Ukuran standar titik dalam matplotlib adalah 72 poin per inci (ppi) - 1 titik karenanya 1/72 inci.

Mungkin bermanfaat untuk menentukan ukuran dalam piksel, bukan titik. Jika angka dpi adalah 72 juga, satu titik adalah satu piksel. Jika angka dpi berbeda (standar matplotlib adalah fig.dpi=100),

1 point == fig.dpi/72. pixels

Sementara ukuran marker sebaran dalam poin karenanya akan terlihat berbeda untuk dpi gambar yang berbeda, orang dapat menghasilkan penanda 10 x 10 piksel ^ 2, yang akan selalu memiliki jumlah piksel yang sama untuk dicakup:

masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini masukkan deskripsi gambar di sini

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

Jika Anda tertarik dengan sebaran unit data, periksa jawaban ini .

ImportanceOfBeingErnest
sumber
Bingung bagaimana seseorang menghitung parameter apa yang harus diberikan untuk menyebarkan untuk mendapatkan lingkaran yang mencakup diameter, katakanlah, 0,1 dalam koordinat nyata plot (sehingga untuk mengisi jarak antara katakanlah 0,4 dan 0,5 pada plot dari (0) , 0) hingga (1,1)?
Anatoly Alekseev
@AnatolyAlekseev Itu harus dijawab oleh pertanyaan ini .
ImportanceOfBeingErnest
21

Anda dapat menggunakan markersize untuk menentukan ukuran lingkaran dalam metode plot

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

Dari sini

masukkan deskripsi gambar di sini

Zhaoqing
sumber
Pertanyaannya adalah tentang scatterplot, dan di matplotlib kedua fungsi plot memiliki parameter yang berbeda ( markersize untuk plot , dan s untuk scatter ). Jadi jawaban ini tidak berlaku.
Dom
3
@ Tom saya terbalik, karena pertanyaan ini muncul sebagai hasil pertama di google bahkan ketika saya mencari "ukuran penanda plot pyplot", jadi jawaban ini membantu.
Przemek D
Saya tahu metode plot dan metode scatter berbeda dalam plt tetapi mereka berdua dapat mewujudkan 'scatter plot' dan menyesuaikan markersize, jadi jawaban ini hanyalah cara lain jika Anda menggunakan metode plot @Dom
zhaoqing
18

Ini adalah area penanda. Maksud saya jika Anda memiliki s1 = 1000dan kemudian s2 = 4000, hubungan antara jari-jari lingkaran masing-masing adalah: r_s2 = 2 * r_s1. Lihat plot berikut:

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

masukkan deskripsi gambar di sini

Saya memiliki keraguan yang sama ketika saya melihat posting, jadi saya melakukan contoh ini kemudian saya menggunakan penggaris di layar untuk mengukur jari-jari.

Joaquin
sumber
Ini adalah jawaban bebas terbersih dan paling gemuk. Terima kasih
Ayan Mitra
6

Saya juga berusaha menggunakan 'sebar' pada awalnya untuk tujuan ini. Setelah sedikit waktu terbuang - saya memutuskan solusi berikut.

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)

masukkan deskripsi gambar di sini

Ini didasarkan pada jawaban untuk pertanyaan ini

Ike
sumber
sangat membantu Tetapi mengapa menggunakan dua loop?
grabantot
1
@ Grabantot tidak ada alasan, hanya tidak berpikir terlalu banyak ke dalamnya.
Ike
2

Jika ukuran lingkaran sesuai dengan kuadrat parameter di s=parameter, maka tetapkan akar kuadrat untuk setiap elemen yang Anda tambahkan ke array ukuran Anda, seperti ini: s=[1, 1.414, 1.73, 2.0, 2.24]sehingga ketika mengambil nilai-nilai ini dan mengembalikannya, peningkatan ukuran relatifnya akan menjadi akar kuadrat dari progresi kuadrat, yang mengembalikan progresi linier.

Jika saya harus persegi masing-masing karena mendapat output ke plot: output=[1, 2, 3, 4, 5]. Coba interpretasi daftar:s=[numpy.sqrt(i) for i in s]

pengguna34028
sumber
1
Seharusnya i in outputtidak?
Sigur