使用 numpy percentile 为每一行获取不同的分位数

Get different quantile for each row using numpy percentile

我想使用 np.percentile 为每一行获取不同的分位数。

例如,给定这个 2 行数组,我想获得第一行的第 20 个百分位数和第二行的第 60 个百分位数。

dat = np.array([[1, 10, 3], [4, -1, 5]])
dat
# array([[ 1, 10,  3],
#        [ 4, -1,  5]])

从第 20 个百分位数开始:

np.percentile(dat, 0.2, axis=1)
# array([ 1.008, -0.98 ])

第 60 个:

np.percentile(dat, 0.6, axis=1)
# array([ 1.024, -0.94 ])

基于此,理想的结果应该是[1.008, -0.94]

将向量作为分位数将结果扩展为 nxn 数组:

np.percentile(dat, [0.2, 0.6], axis=1)
# array([[ 1.008, -0.98 ],
#        [ 1.024, -0.94 ]])

这个结果的对角线产生正确的结果:

np.percentile(dat, [0.2, 0.6], axis=1).diagonal()
# array([ 1.008, -0.94 ])

但这对于较大的阵列来说成本过高。有没有办法直接计算每行对应分位数的百分位数?

将数组转换为 DataFrame 并将所需的分位数作为列后,您可以使用 apply

def percentile_qarray_df(dat, q):
  # dat: numpy array.
  # q: Vector with the same number of rows as dat.
  df = pd.DataFrame(dat)
  df['q'] = q
  return df.apply(lambda x: np.percentile(x.drop('q'), x.q), axis=1)

例如:

percentile_qarray_df(dat, [0.2, 0.6])
# 0    1.008
# 1   -0.940
# dtype: float64

虽然这仍然很慢。

如果数据类型没有冲突,您可以连接百分位数和数据,然后使用 np.apply_along_axis 将百分位数与数据分开:

def percentile_qarray_np(dat, q):
  return np.apply_along_axis(
    lambda x: np.percentile(x[1:], x[0]),
    1,
    np.concatenate([np.array(q)[:, np.newaxis], dat], axis=1)
  )

例如:

n = 10
percentiles = np.linspace(0, 100, n)
a = np.arange(n**2).reshape(n, n)
print(percentile_qarray_np(a, percentiles))

现在在 synthimpute 包中。