Python/Matplotlib: 随机select "sample" 散点不同的marker

Python/Matplotlib: Randomly select "sample" scatter points for different marker

几乎完全符合问题的内容,但有一点背景:

我正在创建一个程序来绘制大量点(~10,000,但稍后会更多)。这是使用 matplotlib 的 plt.scatter 完成的。此命令是保存图形的循环的一部分,因此我可以稍后为其设置动画。

我想做的是随机 select 这些粒子的一小部分(比如说,也许 100 个?)并给它们一个不同于其余部分的标记,即使它们是同一个数据集。这样我就可以将它们用作占位符来查看单个粒子以及大部分粒子的运动 material.

有没有办法对相同数据的一小部分使用不同的标记?

仅供参考,粒子仅使用 numpy 随机采样器均匀分布,但我的代码是:

for i in range(N): # N number of particles
    particle_position[i] = np.random.uniform(0, xmax)  # Initialize in spatial domain
    particle_velocity[i] = np.random.normal(0, 5)      # Initialize in velocity space

for i in range(maxtime):
    plt.scatter(particle_position, particle_velocity, s=1, c=norm_xvel, cmap=br_disc, lw=0)

位置和速度在主循环的每次迭代中发生变化(有相当多的代码),但这些是主要的初始化和绘图例程。

我有一个想法,也许我可以随机 select 一系列来自范围 (N) 的 i 值,并使用 ax.scatter() 命令将它们绘制在相同的轴上?

下面的代码可以满足您的需求。我在正确的范围内(0N)选择了一组 v_sub_indexN_sub 索引,并从较大的 _sub 后缀中抽取这些索引样本 particle_positionparticle_velocity。请注意,您不必循环生成随机样本。 Numpy 具有强大的功能,无需使用 for 循环。

import numpy as np
import matplotlib.pyplot as pl

N = 100
xmax = 1.
v_sigma = 2.5 / 2. # 95% of the samples contained within 0, 5
v_mean  = 2.5      # mean at 2.5

N_sub = 10
v_sub_index = np.random.randint(0, N, N_sub)

particle_position = np.random.rand (N) * xmax
particle_velocity = np.random.randn(N)

particle_position_sub   = np.array(particle_position[v_sub_index])
particle_velocity_sub   = np.array(particle_velocity[v_sub_index])
particle_position_nosub = np.delete(particle_position, v_sub_index)
particle_velocity_nosub = np.delete(particle_velocity, v_sub_index)

pl.scatter(particle_position_nosub, particle_velocity_nosub, color='b', marker='o')
pl.scatter(particle_position_sub  , particle_velocity_sub  , color='r', marker='^')
pl.show()

这里有一个可能的解决方案,可以用不同的标记标识您的一部分点:

import matplotlib.pyplot as plt
import numpy as np

SIZE = 100
SAMPLE_SIZE = 10

def select_subset(seq, size):
    """selects a subset of the data using ...
    """
    return seq[:size]

points_x = np.random.uniform(-1, 1, size=SIZE)
points_y = np.random.uniform(-1, 1, size=SIZE)

plt.scatter(points_x, points_y, marker=".", color="blue")
plt.scatter(select_subset(points_x, SAMPLE_SIZE), 
            select_subset(points_y, SAMPLE_SIZE), 
            marker="o", color="red")

plt.show()

它使用plt.scatter两次;一次在完整数据集上,另一个在样本点上。

您必须决定如何 select 点样本 - 它在 select_subset 函数中被隔离..

您也可以从数据集中提取样本点以防止将它们标记两次,但 numpy 在删除或调整大小方面效率很低。

也许更好的方法是使用口罩?掩码的优点是可以完整且有序地保留原始数据。

下面是处理蒙版的方法:

import matplotlib.pyplot as plt
import numpy as np
import random

SIZE = 100
SAMPLE_SIZE = 10

def make_mask(data_size, sample_size):
    mask = np.array([True] * sample_size + [False ] * (data_size - sample_size))
    np.random.shuffle(mask)
    return mask

points_x = np.random.uniform(-1, 1, size=SIZE)
points_y = np.random.uniform(-1, 1, size=SIZE)
mask = make_mask(SIZE, SAMPLE_SIZE)
not_mask = np.invert(mask)

plt.scatter(points_x[not_mask], points_y[not_mask], marker=".", color="blue")
plt.scatter(points_x[mask], points_y[mask], marker="o", color="red")

plt.show()

如您所见,scatter 在数据点的子集(样本中未 select 的数据点)上调用一次,在采样子集上调用第二次,然后绘制每个子集都有自己的标记。它是高效的并且完整地保留了原始数据。