Размер маркера рассеянного графика
В документе pyplot для точечного графика:
matplotlib.pyplot.scatter (x, y, s = 20, c = 'b', маркер ='o', cmap= нет, норма = нет, vmin= нет, vmax= нет, альфа = нет, ширина линии = нет, faceted=True, verts= Нет, hold = Нет, **kwargs)
Размер маркера
s: размер в пунктах ^2. Это скаляр или массив такой же длины, как x и y.
Что это за единица points^2
? Что это значит? Есть ли s=100
имею в виду 10 pixel x 10 pixel
?
В основном я пытаюсь сделать точечные диаграммы с разными размерами маркеров, и я хочу выяснить, что делает s
среднее число
7 ответов
Это может быть несколько запутанным способом определения размера, но вы в основном указываете область маркера. Это означает, что для удвоения ширины (или высоты) маркера вам нужно увеличить 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
не радиус, поэтому видимый размер масштабируется линейно с площадью.
Потому что другие ответы здесь утверждают, что s
обозначает область маркера, я добавляю этот ответ, чтобы прояснить, что это не обязательно так.
Размер в баллах ^2
Аргумент s
в plt.scatter
обозначает markersize**2
, Как сказано в документации
s
: scalar или array_like, shape (n,), необязательный
размер в баллах ^2. По умолчанию используется rcParams['lines.markersize'] ** 2.
Это можно воспринимать буквально. Для того, чтобы получить маркер, который х точек большой, вам нужно возвести это число в квадрат и дать его 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, одна точка - один пиксель. Если число точек на дюйм отличается (по умолчанию 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()
Это площадь маркера. Я имею в виду, если у вас есть 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')
У меня возникли те же сомнения, когда я увидел сообщение, поэтому я сделал этот пример, затем использовал линейку на экране для измерения радиусов.
Вы можете использовать размер маркера, чтобы указать размер круга в методе построения
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()
Я также попытался сначала использовать "разброс" для этой цели. После довольно много потерянного времени - я остановился на следующем решении.
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)
Это основано на ответе на этот вопрос
Поскольку это самый популярный результат поисковой системы по запросу « как изменить размеры маркеров точечной диаграммы в Python », вот сводка определений размеров маркеров точечной диаграммы в некоторых из самых популярных библиотек построения графиков в Python:
- matplotlib (где
s=markersize**2
):-
plt.scatter(x, y, s=9)
-
plt.plot(x, y, 'o', markersize=3)
-
- панды:
-
df.plot(x='A', y='B', kind='scatter', s=9)
-
df.plot(x='A', y='B', marker='o', linestyle='', markersize=3)
-
- морской житель:
sns.scatterplot(x=x, y=y, s=9)
Что касается размера маркера точечной диаграммы, здесь не упомянута одна важная вещь: каждый маркер определяет цвет и ширину края, и в зависимости от того, как они установлены, результирующие маркеры могут иметь разные размеры.
По умолчанию вокруг маркеров рисуется край с шириной = 1 (), что увеличивает размер маркеров. Как вы можете видеть из следующего кода, если мы удалим краевые линии (на ), мы получим маркер гораздо меньшего размера. Фактически,s=1
иlw=1
рисует маркер того же размера, что иs=4
иlw=0
.
fig, ax = plt.subplots(figsize=(6/72, 2/72), dpi=72*50)
ax.scatter([-0.3], [0], s=1, lw=0)
ax.scatter([1.5], [0], s=1)
ax.scatter([3.8], [0], s=4, lw=0)
ax.set(position=[0,0,1,1], xticks=[], yticks=[], xlim=(-1,5))
plt.setp(ax.spines.values(), linewidth=0.01);
Более конкретный пример: на следующем рисунке тот же размер маркера (s=36
) был передан в плоттеры точечной диаграммы seaborn, matplotlib и pandas, но поскольку цвет края по умолчанию и ширина края маркера в seaborn отличаются от цветов в двух других методах, точечные диаграммы в конечном итоге имеют маркеры разных размеров.
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
x = range(20)
df = pd.DataFrame({'A': x, 'B': x})
fig, axs = plt.subplots(1, 3, figsize=(15,3), facecolor='white')
sns.scatterplot(x=x, y=x, ax=axs[0], s=36);
axs[1].scatter(x, x, s=36);
df.plot.scatter('A', 'B', ax=axs[2], s=36);
ms = {f"ax{i}": ax.collections[0] for i, ax in enumerate(axs)}
axs[0].set_title(f"seaborn scatterplot\nmarker edgewidth: {ms['ax0'].get_lw()[0]}\nedgecolor: {ms['ax0'].get_ec()[0]}")
axs[1].set_title(f"matplotlib scatter\nmarker edgewidth: {ms['ax1'].get_lw()[0]}\nedgecolor: {ms['ax1'].get_ec()[0].round(2)}");
axs[2].set_title(f"pandas scatter plot\nmarker edgewidth: {ms['ax2'].get_lw()[0]}\nedgecolor: {ms['ax2'].get_ec()[0].round(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]