python - 沿 Numpy 阵列轴的质心标准偏差

标签 python python-2.7 numpy standard-deviation weighted-average

我正在尝试找到一种性能良好的方法来计算沿 Numpy 数组轴的质心/重力中心的标准偏差。

在公式中这是(抱歉错位):

我能想到的最好的是:

def weighted_com(A, axis, weights):
    average = np.average(A, axis=axis, weights=weights)
    return average * weights.sum() / A.sum(axis=axis).astype(float)

def weighted_std(A, axis):
    weights = np.arange(A.shape[axis])
    w1com2 = weighted_com(A, axis, weights)**2
    w2com1 = weighted_com(A, axis, weights**2)
    return np.sqrt(w2com1 - w1com2)

weighted_com 中,我需要更正从权重总和到值总和的归一化(我想这是一个丑陋的解决方法)。 weighted_std 可能没问题。

为了避免 XY 问题,我仍然要求我真正想要的(更好的 weighted_std)而不是我的 weighted_com 的更好版本。

.astype(float) 是一种安全措施,因为我会将其应用于包含整数的直方图,当不在 Python 3 中或 from __future__ 时,由于整数除法会导致问题进口部门不活跃。

最佳答案

您想取向量 [1, 2, 3, ..., n] 的均值、方差和标准差— 其中n是输入矩阵的维数 A沿着感兴趣的轴 —,权重由矩阵 A 给出本身。

为了具体起见,假设您想考虑沿垂直轴 (axis=0) 的这些质心统计数据——这与您编写的公式相对应。对于固定列 j , 你会做

n = A.shape[0]
r = np.arange(1, n+1)
mu = np.average(r, weights=A[:,j])
var = np.average(r**2, weights=A[:,j]) - mu**2
std = np.sqrt(var)

为了将不同列的所有计算放在一起,您必须将 r 的一堆副本堆叠在一起。 (每列一个)形成一个矩阵(我在下面的代码中调用了 R)。稍加小心,您就可以同时为这两者工作 axis=0axis=1 .

import numpy as np

def com_stats(A, axis=0):
    A = A.astype(float)    # if you are worried about int vs. float
    n = A.shape[axis]
    m = A.shape[(axis-1)%2]
    r = np.arange(1, n+1)
    R = np.vstack([r] * m)
    if axis == 0:
        R = R.T

    mu = np.average(R, axis=axis, weights=A)
    var = np.average(R**2, axis=axis, weights=A) - mu**2
    std = np.sqrt(var)
    return mu, var, std

例如,

A = np.array([[1, 1, 0], [1, 2, 1], [1, 1, 1]])
print(A)

# [[1 1 0]
#  [1 2 1]
#  [1 1 1]]

print(com_stats(A))

# (array([ 2. ,  2. ,  2.5]),                   # centre-of-mass mean by column
#  array([ 0.66666667,  0.5       ,  0.25  ]),  # centre-of-mass variance by column
#  array([ 0.81649658,  0.70710678,  0.5   ]))  # centre-of-mass std by column

编辑:

可以避免创建 r 的内存副本 build R通过使用 numpy.lib.stride_tricks : 换行

R = np.vstack([r] * m)

上面有

from numpy.lib.stride_tricks import as_strided
R = as_strided(r, strides=(0, r.itemsize), shape=(m, n))

结果R是一个(跨步)ndarray其底层数组与 r 相同的 — 绝对不会复制任何值。

from numpy.lib.stride_tricks import as_strided

FMT = '''\
Shape: {}
Strides: {}
Position in memory: {}
Size in memory (bytes): {}
'''

def find_base_nbytes(obj):
    if obj.base is not None:
        return find_base_nbytes(obj.base)
    return obj.nbytes

def stats(obj):
    return FMT.format(obj.shape,
                      obj.strides,
                      obj.__array_interface__['data'][0],
                      find_base_nbytes(obj))

n=10
m=1000
r = np.arange(1, n+1)
R = np.vstack([r] * m)
S = as_strided(r, strides=(0, r.itemsize), shape=(m, n))

print(stats(r))
print(stats(R))
print(stats(S))

输出:

Shape: (10,)
Strides: (8,)
Position in memory: 4299744576
Size in memory (bytes): 80

Shape: (1000, 10)
Strides: (80, 8)
Position in memory: 4304464384
Size in memory (bytes): 80000

Shape: (1000, 10)
Strides: (0, 8)
Position in memory: 4299744576
Size in memory (bytes): 80

归功于 this SO answerthis one有关如何获取 strided ndarray 的底层数组的内存地址和大小的说明.

关于python - 沿 Numpy 阵列轴的质心标准偏差,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38556297/

相关文章:

python - MD5 哈希 转到 Python

python - 行之间的条件数学运算

numpy - 计算 xarray 中每个网格点的百分位

Python(17874,0x111e92dc0)malloc : can't allocate region

python - python 中的函数会更改输入变量,这是为什么?

python - matplotlib中图例中的重复项目?

python - 从两个列表中创建一个新列表,其中一个列表缺少数据 - 只应接受有效的对应值

python - np.沿轴减去

python - 防止按键出现在屏幕上

python - 多处理时全局变量的名称错误,仅在子目录中