розмір маркера сюжету розсипу 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, мені здається, це не так, оскільки один знаходиться в пікселях (маркерний розмір), а інший - у цій дивній одиниці квадратних точок (розмір). Це завжди мене бентежить, але я вважаю, що це стосується розміру маркера розсіювання, який використовується для позначення кількості візуально пропорційно.
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 Ваша інтуїція правильна, з мого боку це неправильне формулювання (як варіант, поганий вибір масштабування осі x). Я пояснив ще декілька в редакції, оскільки це було занадто довго для коментарів.
День

1
Чи можливо змінити sзначення відповідно до розміру вікна рисунка? Я маю на увазі, якщо ми максимізуємо вікна фігури, я хотів би мати більші розміри розмірів.
Сигур

2
Чудовий приклад (просто необхідні речі!). Це не повинно бути 4 ** nі 2 ** n, але n ** 4і n ** 2. З 2 ** nдругим сюжетом не масштабується лінійно за діаметром кола. Це все ще надто швидко йде (тільки не так сильно над вершиною).
Томаш

1
Якщо коротше - другий сюжет показує квадратний корінь експоненціалу - що є ще одним експоненційним, трохи менш крутим.
Томаш

217

Оскільки інші відповіді тут стверджують, що sпозначає область маркера, я додаю цю відповідь, щоб уточнити, що це не обов'язково.

Розмір у балах ^ 2

Аргумент sв plt.scatterОзначає markersize**2. Як йдеться в документації

s: скалярний чи масив_подібний, форма (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параметру . Це мотивація називати це "областю", хоча в більшості випадків насправді це не так.

Визначення розміру маркерів розсіювання з точки зору деякої кількості, пропорційної площі маркера, має в цьому сенсі сенс, оскільки саме площа маркера сприймається при порівнянні різних пластирів, а не його бічна довжина чи діаметр. Тобто подвоєння базової кількості повинно подвоїти площу маркера.

введіть тут опис зображення

Що таке бали?

Поки що відповідь на те, що означає розмір маркера розкидання, наведено в одиницях балів. Бали часто використовуються в типографії, де шрифти вказані в точках. Також частота ліній часто вказується в пунктах. Стандартний розмір балів у matplotlib - 72 бали на дюйм (ppi) - 1 бал, отже, 1/72 дюйма.

Можливо, буде корисно мати можливість вказувати розміри в пікселях замість очок. Якщо цифра dpi також 72, то одна точка - один піксель. Якщо цифра dpi відрізняється (значення за замовчуванням matplotlib fig.dpi=100),

1 point == fig.dpi/72. pixels

Хоча розмір маркера розсіювання в точках, отже, виглядатиме різним для різних зображень у точці на дюйм, можна створити маркер 10 на 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)?
Анатолій Алексєєв

@AnatolyAlekseev Що повинно відповісти цей питання.
ВажливістьBeingErnest

21

Ви можете використовувати маркерний розмір, щоб вказати розмір кола в методі сюжету

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

від сюди

введіть тут опис зображення


Питання стосувалося розсіювання, а в matplotlib дві функції побудови графіку мають різні параметри ( маркер розміру для ділянки , а s для розсіювання ). Тому ця відповідь не застосовується.
Дом

3
@Dom я схвалив, тому що це запитання з'являється як перший результат у 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')

введіть тут опис зображення

У мене були такі самі сумніви, коли я побачив пост, тому я зробив цей приклад, тоді я використав лінійку на екрані для вимірювання радіусів.


Це найчистіша і найбезжирніша відповідь. Спасибі
Аян Мітра

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)

введіть тут опис зображення

На цьому грунтується відповідь на це питання


дуже корисно. Але навіщо використовувати дві петлі?
грабантот

1
@grabantot без причин, просто не надто замислювався над цим.
Айк

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не повинні?
Сігур
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.