使用matplotlib更新散点图中的标记样式 [英] Updating marker style in scatter plot with matplotlib

查看:401
本文介绍了使用matplotlib更新散点图中的标记样式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个交互式绘图应用程序,该应用程序要求用户从matplotlib散点图中选择数据点.为了清楚起见,我希望能够在单击(或以任何方式选择)绘制点时更改其颜色和形状.

I am working on an interactive plotting application which requires users to select data points from a matplotlib scatter plot. For clarity, I would like to be able to alter the colour and shape of a plotted point when it is clicked on (or selected by any means).

由于matplotlib.collections.PathCollection类具有set_facecolors方法,因此更改点的颜色相对简单.但是,我看不到更新标记形状的类似方法.

As the matplotlib.collections.PathCollection class has a set_facecolors method, altering the color of the points is relatively simple. However, I cannot see a similar way to update the marker shape.

有没有办法做到这一点?

Is there a way to do this?

该问题的准系统说明:

import numpy as np
import matplotlib.pyplot as plt

x = np.random.normal(0,1.0,100)
y = np.random.normal(0,1.0,100)

scatter_plot = plt.scatter(x, y, facecolor="b", marker="o")

#update the colour 
new_facecolors = ["r","g"]*50
scatter_plot.set_facecolors(new_facecolors)

#update the marker? 
#new_marker = ["o","s"]*50
#scatter_plot.???(new_marker)  #<--how do I access the marker shapes?  

plt.show()

有什么想法吗?

推荐答案

如果您真正想要的是突出显示用户选择的点,则可以在所选点的上方叠加另一个点(带有dot = ax.scatter(...)) .稍后,响应用户的点击,您可以使用dot.set_offsets((x, y))更改点的位置.

If what you are really after is highlighting the point selected by the user, then you could superimpose another dot (with dot = ax.scatter(...)) on top of the point selected. Later, in response to user clicks, you could then use dot.set_offsets((x, y)) to change the location of the dot.

Joe Kington编写了一个出色的示例(DataCursor),该示例如何添加注释,以在显示以下内容时显示数据坐标用户点击艺术家(例如散点图).

Joe Kington has written a wonderful example (DataCursor) of how to add an annotation displaying the data coordinates when a user clicks on on artist (such as a scatter plot).

这是一个派生示例(FollowDotCursor),当用户将鼠标悬停在某个点上时,它会突出显示和注释数据点.

Here is a derivative example (FollowDotCursor) which highlights and annotates data points when a user hovers the mouse over a point.

通过DataCursor,显示的数据坐标是用户单击的位置-可能与基础数据不完全相同.

With the DataCursor the data coordinates displayed are where the user clicks -- which might not be exactly the same coordinates as the underlying data.

使用FollowDotCursor时,显示的数据坐标始终是基础数据中最接近鼠标的点.

With the FollowDotCursor the data coordinate displayed is always a point in the underlying data which is nearest the mouse.

import numpy as np
import matplotlib.pyplot as plt
import scipy.spatial as spatial

def fmt(x, y):
    return 'x: {x:0.2f}\ny: {y:0.2f}'.format(x=x, y=y)

class FollowDotCursor(object):
    """Display the x,y location of the nearest data point.
    """
    def __init__(self, ax, x, y, tolerance=5, formatter=fmt, offsets=(-20, 20)):
        try:
            x = np.asarray(x, dtype='float')
        except (TypeError, ValueError):
            x = np.asarray(mdates.date2num(x), dtype='float')
        y = np.asarray(y, dtype='float')
        self._points = np.column_stack((x, y))
        self.offsets = offsets
        self.scale = x.ptp()
        self.scale = y.ptp() / self.scale if self.scale else 1
        self.tree = spatial.cKDTree(self.scaled(self._points))
        self.formatter = formatter
        self.tolerance = tolerance
        self.ax = ax
        self.fig = ax.figure
        self.ax.xaxis.set_label_position('top')
        self.dot = ax.scatter(
            [x.min()], [y.min()], s=130, color='green', alpha=0.7)
        self.annotation = self.setup_annotation()
        plt.connect('motion_notify_event', self)

    def scaled(self, points):
        points = np.asarray(points)
        return points * (self.scale, 1)

    def __call__(self, event):
        ax = self.ax
        # event.inaxes is always the current axis. If you use twinx, ax could be
        # a different axis.
        if event.inaxes == ax:
            x, y = event.xdata, event.ydata
        elif event.inaxes is None:
            return
        else:
            inv = ax.transData.inverted()
            x, y = inv.transform([(event.x, event.y)]).ravel()
        annotation = self.annotation
        x, y = self.snap(x, y)
        annotation.xy = x, y
        annotation.set_text(self.formatter(x, y))
        self.dot.set_offsets((x, y))
        bbox = ax.viewLim
        event.canvas.draw()

    def setup_annotation(self):
        """Draw and hide the annotation box."""
        annotation = self.ax.annotate(
            '', xy=(0, 0), ha = 'right',
            xytext = self.offsets, textcoords = 'offset points', va = 'bottom',
            bbox = dict(
                boxstyle='round,pad=0.5', fc='yellow', alpha=0.75),
            arrowprops = dict(
                arrowstyle='->', connectionstyle='arc3,rad=0'))
        return annotation

    def snap(self, x, y):
        """Return the value in self.tree closest to x, y."""
        dist, idx = self.tree.query(self.scaled((x, y)), k=1, p=1)
        try:
            return self._points[idx]
        except IndexError:
            # IndexError: index out of bounds
            return self._points[0]

x = np.random.normal(0,1.0,100)
y = np.random.normal(0,1.0,100)
fig, ax = plt.subplots()

cursor = FollowDotCursor(ax, x, y, formatter=fmt, tolerance=20)
scatter_plot = plt.scatter(x, y, facecolor="b", marker="o")

#update the colour 
new_facecolors = ["r","g"]*50
scatter_plot.set_facecolors(new_facecolors)    

plt.show()

这篇关于使用matplotlib更新散点图中的标记样式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆