【问题标题】:How to access/change properties of individual points on matplotlib scatter plot如何访问/更改 matplotlib 散点图上各个点的属性
【发布时间】:2022-01-12 23:12:31
【问题描述】:

有没有办法可以修改 matplotlib 散点图上各个点的属性,例如使某些点不可见或改变它们的大小/形状?

让我们考虑使用 pandas.DataFrame() 的示例数据集:

import pandas as pd
import matplotlib.pyplot as plt
import random

df = pd.DataFrame()
df['name'] = ['cat', 'dog', 'bird', 'fish', 'frog']
df['id'] = [1, 1, 1, 2, 2]
df['x'] = [random.randint(-10, 10) for n in range(5)]
df['y'] = [random.randint(-10, 10) for n in range(5)]

让我们在散点图上绘制它:

sc = plt.scatter(df['x'].tolist(), df['y'].tolist())
plt.show()
#easy-peasy

绘图已生成。

假设我希望从现有绘图中删除所有 df 中 id=1 的数据点(例如单击按钮)。删除我并不一定意味着删除。设置不可见或其他什么都可以。总的来说,我对迭代情节上存在的每个点并对其进行处理的方法很感兴趣。

编辑#1

使用inspect 模块我注意到sc 绘图对象拥有名为sc._offsets 的属性。 这些似乎是 2D numpy 数组,在散点图上保存数据点的坐标(对于 2D 图)。 这个_offsets 属性由2 个组件组成? .. 我应该说吗?:“数据”(二维坐标数组)和“掩码”(布尔值的二维数组:在这种情况下 = False)和“填充值”,这似乎与我无关。

我已经设法通过删除某些索引处的 _offsets 元素来从散点图中删除选择点,如下所示:

sc._offsets = numpy.delete(sc._offsets, [0, 1, 3], axis=0)

然后重新绘制情节:

sc.figure.canvas.draw()

由于数据框的“id”列中的值和 sc._offsets 中的坐标是对齐的,我可以通过索引删除坐标,其中“id”值(例如)= 1。 这就是我想要的,因为带有数据集的原始数据框保持不变,因此我可以根据需要在散点图上重新创建点。

我想我可以使用“掩码”以某种方式隐藏/显示散点图上的选择点,但我还不知道如何。我正在调查。

【问题讨论】:

  • 您希望生成的绘图是交互式的吗?
  • 是的。我想在绘图实时生成后影响点。
  • 你可以用 ipywidgets 做到这一点。你的环境是什么——jupyter?
  • 只是普通的标准 Python 3.8 解释器。我宁愿坚持下去。
  • 你需要某种interactive GUI to hold the figure。但是,请查看 this documentation on interactive figures 中带有 onpick 函数的示例。

标签: python pandas matplotlib scatter-plot


【解决方案1】:

已解决

答案是设置 numpy.core.ma.MaskedArray 的掩码,它位于 matplotlib 散点图的 sc._offsets.mask 属性下。 这可以在绘图生成期间和生成绘图之后以交互模式通过以下方式完成:

#before change:
#sc._offsets.mask = [[False, False], [False, False], [False, False], [False, False], [False, False]]

sc._offsets.mask = [[1, 1], [1, 1], [1, 1], [0, 0], [0, 0]]

#after change:
#sc._offsets.mask = [[True, True], [True, True], [True, True], [False, False], [False, False]]

#then re-draw plot
sc.figure.canvas.draw() #docs say that it's better to use draw_idle() but I don't see difference

设置为 True 值对应于要从绘图中排除的点的索引,从绘图中删除该特定点。它不会“删除”它。可以通过将布尔值设置回“False”来恢复点。请注意,它是二维数组,因此传递简单:[1, 1, 1, 0, 0] 不会,您需要考虑绘图的 x 和 y 坐标。

有关详细信息,请参阅 numpy 文档: https://numpy.org/doc/stable/reference/maskedarray.generic.html#accessing-the-mask

如果出现问题,我会进行编辑。 谢谢大家的帮助。

【讨论】:

    【解决方案2】:

    一个基本的解决方案。如果您的数据集不是很大,并且您知道区分数据的条件,您想要以不同的方式绘制,您可以为每个条件创建一列,并用不同的标记和颜色绘制每个条件。

    假设您要绘制不同的大于 3 的 y:

    import pandas as pd
    import matplotlib.pyplot as plt
    import random
    
    df = pd.DataFrame()
    df['name'] = ['cat', 'dog', 'bird', 'fish', 'frog']
    df['id'] = [1, 1, 1, 2, 2]
    df['x'] = [random.randint(-10, 10) for n in range(5)]
    df['y'] = [random.randint(-10, 10) for n in range(5)]
    
    _mask = df.y > 3  
    df.loc[_mask, 'y_case_2'] = df.y
    df.loc[~_mask, 'y_case_1'] = df.y 
    
    sc = plt.scatter(df.x, df.y_case_1, marker='*', color='r')
    sc = plt.scatter(df.x, df.y_case_2, marker='.', color='b')
    plt.show()
    df
    
    

    注意:请注意,随机数据无法生成大于 3 的数据。如果是,请重试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-29
      • 2020-02-24
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 1970-01-01
      • 2016-04-28
      • 1970-01-01
      相关资源
      最近更新 更多