【问题标题】:How to use numpy to calculate mean and standard deviation of an irregular shaped array如何使用 numpy 计算不规则形状数组的均值和标准差
【发布时间】:2017-06-01 07:41:42
【问题描述】:

我有一个 numpy 数组,其中包含许多不同长度的样本

Samples = np.array([[1001, 1002, 1003],
                    ... ,
                    [1001, 1002]])

我想(按元素)减去数组的平均值,然后除以数组的标准差。比如:

newSamples = (Samples-np.mean(Samples))/np.std(Samples)

除非它不适用于不规则形状的数组,

np.mean(Samples) 原因

unsupported operand type(s) for /: 'list' and 'int'

由于我假设它为每个轴设置了一个静态大小,然后当它遇到不同大小的样本时它无法处理它。使用 numpy 解决此问题的方法是什么?

示例输入:

Sample = np.array([[1, 2, 3],
                   [1, 2]])

减去均值再除以标准差:

Sample = array([[-1.06904497,  0.26726124,  1.60356745], 
                [-1.06904497,  0.26726124]])

【问题讨论】:

标签: python arrays numpy


【解决方案1】:

不要制作参差不齐的数组。只是不要。 Numpy 不能用它们做很多事情,你可能为它们编写的任何代码都将总是不可靠和缓慢的,因为 numpy 不能那样工作。它将它们变成object dtypes:

Sample
array([[1, 2, 3], [1, 2]], dtype=object)

几乎没有numpy 函数可以使用。在这种情况下,这些对象是list 对象,这会使您的代码更加混乱,因为您必须在listndarray 方法之间切换,或者坚持使用列表安全的numpy 方法。这是一个灾难的秘诀,因为以后任何人(即使是你自己,如果你忘记了)在代码中闲逛的人都会在雷区跳舞。

您可以对数据做两件事来让事情变得更好:

第一种方法是索引和展平。

i = np.cumsum(np.array([len(x) for x in Sample]))
flat_sample = np.hstack(Sample)

这会保留i中每个样本的结尾索引,同时将样本保持为一维数组

另一种方法是用np.nan 填充一个维度并使用nan-safe 函数

m = np.array([len(x) for x in Sample]).max()
nan_sample = np.array([x + [np.nan] * (m - len(x)) for x in Sample])

所以要进行计算,您可以使用flat_sample 并执行与上述类似的操作:

new_flat_sample = (flat_sample - np.mean(flat_sample)) / np.std(flat_sample) 

并使用i 重新创建您的原始数组(或我推荐的数组列表:参见np.split)。

new_list_sample = np.split(new_flat_sample, i[:-1])

[array([-1.06904497,  0.26726124,  1.60356745]),
 array([-1.06904497,  0.26726124])]

或使用nan_sample,但您需要将np.meannp.std 替换为np.nanmeannp.nanstd

new_nan_sample = (nan_sample - np.nanmean(nan_sample)) / np.nanstd(nan_sample)

array([[-1.06904497,  0.26726124,  1.60356745],
       [-1.06904497,  0.26726124,         nan]])

【讨论】:

    【解决方案2】:

    @MichaelHackman(在评论之后)。 这很奇怪,因为当我计算整体标准并平均然后应用它时,我得到了不同的结果(见下面的代码)。

    import numpy as np
    
    Samples = np.array([[1, 2, 3],
                       [1, 2]])
    c = np.hstack(Samples)  # Will gives [1,2,3,1,2]
    mean, std = np.mean(c), np.std(c)
    newSamples = np.asarray([(np.array(xi)-mean)/std for xi in Samples])
    print newSamples
    # [array([-1.06904497,  0.26726124,  1.60356745]), array([-1.06904497,  0.26726124])]
    

    编辑:添加 np.asarray(),将 mean,std 计算放在 Imanol Luengo 出色的 cmets 之后的循环之外(谢谢!)

    【讨论】:

    • 是的,你是对的!我忘记更改正在使用的代码,但我已经编辑了问题以反映更改。感谢您了解这一点。
    • 哦,等一下,我得到的结果肯定和你现在不同
    • @MichaelHackman 可以在我手动检查时更新问题吗?
    • 嗯,这与我得到的输出完全相同:)
    • 另一个小评论,只是为了效率问题:在列表理解之外预先计算 avg = np.mean(c)std = np.std(c) 以避免多次计算。特别适用于大型数组。
    猜你喜欢
    • 1970-01-01
    • 2017-11-07
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 2021-05-08
    • 2014-03-21
    相关资源
    最近更新 更多