Сценарий рассеяния Python.Размер и стиль маркера - PullRequest
38 голосов
/ 31 января 2012

У меня есть набор данных, которые я хочу показать в виде точечной диаграммы. Я хочу, чтобы каждая точка была построена в виде квадрата размером dx.

          x = [0.5,0.1,0.3]
          y = [0.2,0.7,0.8]
          z = [10.,15.,12.]
          dx = [0.05,0.2,0.1]

          scatter(x,y,c=z,s=dx,marker='s')

Проблема в том, что размер s, который читает функция разброса, находится в точках ^ 2. То, что я хотел бы, чтобы каждая точка была представлена ​​квадратом области dx ^ 2, где эта область в «реальных» единицах, единицах графика. Я надеюсь, что вы можете понять это.

У меня тоже есть другой вопрос. Функция разброса отображает маркеры с черной рамкой, как я могу отказаться от этой опции и вообще не иметь рамки?

Ответы [ 4 ]

41 голосов
/ 31 января 2012

Преобразование из пользовательских данных системы координат в отображение системы координат.

и использование edgecolors = 'none' для построения граней без контуров.

import numpy as np

fig = figure()
ax = fig.add_subplot(111)
dx_in_points = np.diff(ax.transData.transform(zip([0]*len(dx), dx))) 
scatter(x,y,c=z,s=dx_in_points**2,marker='s', edgecolors='none')
21 голосов
/ 31 января 2012

Если вам нужны маркеры, размер которых изменяется с размером рисунка, вы можете использовать патчи:

from matplotlib import pyplot as plt
from matplotlib.patches import Rectangle

x = [0.5, 0.1, 0.3]
y = [0.2 ,0.7, 0.8]
z = [10, 15, 12]
dx = [0.05, 0.2, 0.1]

cmap = plt.cm.hot
fig = plt.figure()
ax = fig.add_subplot(111, aspect='equal')

for x, y, c, h in zip(x, y, z, dx):
    ax.add_artist(Rectangle(xy=(x, y),
                  color=cmap(c**2),        # I did c**2 to get nice colors from your numbers
                  width=h, height=h))      # Gives a square of area h*h

plt.show()

enter image description here

Обратите внимание:

  1. квадраты не центрированы в (x,y).x, y на самом деле координаты квадрата внизу слева.Я позволил это таким образом, чтобы упростить мой код.Вы должны использовать (x + dx/2, y + dx/2).
  2. Цвет получен из горячей цветовой карты.Я использовал z ** 2, чтобы дать цвета.Вы также должны адаптировать это к вашим потребностям

Наконец, для вашего второго вопроса.Вы можете получить границы меток разброса, используя ключевое слово arguments edgecolor или edgecolors.Это цветовой аргумент matplotlib или последовательность кортежей rgba соответственно.Если для параметра установлено значение «Нет», границы не отображаются.

18 голосов
/ 04 июля 2014

Я думаю, что мы можем сделать это лучше с помощью коллекции патчей.Согласно документам:

Это (PatchCollection) облегчает присвоение цветовой карты разнородной коллекции исправлений.

Это также может улучшить скорость печати , поскольку PatchCollection будет рисовать быстрее, чем большое количество патчей.

Предположим, вы хотите построить график рассеяния окружностей с данным радиусом в блоке данных:

def circles(x, y, s, c='b', vmin=None, vmax=None, **kwargs):
    """
    Make a scatter of circles plot of x vs y, where x and y are sequence 
    like objects of the same lengths. The size of circles are in data scale.

    Parameters
    ----------
    x,y : scalar or array_like, shape (n, )
        Input data
    s : scalar or array_like, shape (n, ) 
        Radius of circle in data unit.
    c : color or sequence of color, optional, default : 'b'
        `c` can be a single color format string, or a sequence of color
        specifications of length `N`, or a sequence of `N` numbers to be
        mapped to colors using the `cmap` and `norm` specified via kwargs.
        Note that `c` should not be a single numeric RGB or RGBA sequence 
        because that is indistinguishable from an array of values
        to be colormapped. (If you insist, use `color` instead.)  
        `c` can be a 2-D array in which the rows are RGB or RGBA, however. 
    vmin, vmax : scalar, optional, default: None
        `vmin` and `vmax` are used in conjunction with `norm` to normalize
        luminance data.  If either are `None`, the min and max of the
        color array is used.
    kwargs : `~matplotlib.collections.Collection` properties
        Eg. alpha, edgecolor(ec), facecolor(fc), linewidth(lw), linestyle(ls), 
        norm, cmap, transform, etc.

    Returns
    -------
    paths : `~matplotlib.collections.PathCollection`

    Examples
    --------
    a = np.arange(11)
    circles(a, a, a*0.2, c=a, alpha=0.5, edgecolor='none')
    plt.colorbar()

    License
    --------
    This code is under [The BSD 3-Clause License]
    (http://opensource.org/licenses/BSD-3-Clause)
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.patches import Circle
    from matplotlib.collections import PatchCollection

    if np.isscalar(c):
        kwargs.setdefault('color', c)
        c = None
    if 'fc' in kwargs: kwargs.setdefault('facecolor', kwargs.pop('fc'))
    if 'ec' in kwargs: kwargs.setdefault('edgecolor', kwargs.pop('ec'))
    if 'ls' in kwargs: kwargs.setdefault('linestyle', kwargs.pop('ls'))
    if 'lw' in kwargs: kwargs.setdefault('linewidth', kwargs.pop('lw'))

    patches = [Circle((x_, y_), s_) for x_, y_, s_ in np.broadcast(x, y, s)]
    collection = PatchCollection(patches, **kwargs)
    if c is not None:
        collection.set_array(np.asarray(c))
        collection.set_clim(vmin, vmax)

    ax = plt.gca()
    ax.add_collection(collection)
    ax.autoscale_view()
    if c is not None:
        plt.sci(collection)
    return collection

Все аргументы и ключевые слова (кроме marker) функции scatter будут работать аналогичным образом.Я написал суть , включая круги , эллипсы и квадраты / прямоугольники ,Если вам нужна коллекция другой формы, вы можете изменить ее самостоятельно.

Если вы хотите построить colorbar , просто запустите colorbar() или передайте возвращенный объект коллекции в функцию colorbar.

Пример:

from pylab import *
figure(figsize=(6,4))
ax = subplot(aspect='equal')

#plot a set of circle
a = arange(11)
out = circles(a, a, a*0.2, c=a, alpha=0.5, ec='none')
colorbar()

#plot one circle (the lower-right one)
circles(1, 0, 0.4, 'r', ls='--', lw=5, fc='none', transform=ax.transAxes)

xlim(0,10)
ylim(0,10)

Выход:

Example Figure

0 голосов
/ 28 ноября 2015

Чтобы сделать этот Python 3 совместимым, я добавил следующий фрагмент кода

try:
    basestring
except NameError:
    basestring = str

из

Как проверить, является ли переменная строкой с совместимостью с Python 2 и 3

Это необходимо, поскольку basestring недоступен в Python 3. В Python 2 целью basestring было включение как str, так и unicode.В Python 3 нет разницы между str и unicode, и это просто str.

...