一个大型掩蔽阵列的Numpy平均值

2024-04-16 04:50:23 发布

您现在位置:Python中文网/ 问答频道 /正文

从大型屏蔽数组中获取平均值的合适方法是什么?通常我只调用.mean(),但对于非常大的数组,这对我来说是失败的。在

考虑创建一个由一百万个元素组成的数组,所有元素的值都为500,例如:

a = np.ones(1000000, dtype=np.int16) * 500

然后创建一个随机掩码,并将两者合并到一个新的masked array

^{pr2}$

数组b继承dtype,也是int16。在

b中获得平均值可以用不同的方法来完成,但都会得到相同的结果。但是non-ma函数忽略了掩码,不应该使用。在

print(np.average(b), np.mean(b), np.ma.average(b), np.ma.mean(b))
(500.0, 500.0, 500.0, 500.0)

但是,如果将原始数组大小从一百万增加到一千万,结果是:

print(np.average(b), np.mean(b), np.ma.average(b), np.ma.mean(b))
(500.0, -359.19365132075774, -359.19365132075774, -359.19365132075774)

现在只有np.average看起来是正确的,但是正如前面所说的那样,忽略掩码并计算整个数组的平均值,这可以在用b[b.mask] = 1000更改一些掩码值时显示出来。我希望np.mean也能这样做。在

将掩码数组b转换为float32会导致:

b = b.astype(np.float32)
print(np.average(b), np.mean(b), np.ma.average(b), np.ma.mean(b))
(511.18945, 510.37895680000003, 510.37895680000003, 510.37895680000003)

将屏蔽数组b转换为float64(根据文档,默认情况下应该这样做)结果是:

b = b.astype(np.float64)
print(np.average(b), np.mean(b), np.ma.average(b), np.ma.mean(b))
(500.0, 500.0, 500.0, 500.0)

因此,转换为float64似乎可以工作,但我宁愿避免这种情况,因为它会增加内存占用。在

在测试其中一些内容时,我还注意到,如果大小为一百万,对非屏蔽数组(a)调用np.ma.average会给出正确的结果,而当大小为1000万时,则会给出错误的结果,而{}对这两种大小都是正确的。在

有人能解释一下这个例子中dtype和数组的size之间的关系吗?这种情况何时发生以及如何妥善处理对我来说有点神秘。在

所有这些都是在一台64位Win7机器上的Numpy1.8.1中完成的。通过conda安装。在

这是一个复制我所做的事情的笔记本:

http://nbviewer.ipython.org/gist/RutgerK/69b60da73f464900310a


Tags: 方法元素np情况数组mean平均值屏蔽
1条回答
网友
1楼 · 发布于 2024-04-16 04:50:23

this can be shown when changing some of the masked values with b[b.mask] = 1000 for example. I would expect np.mean to do the same though.

这是不正确的,如果存在掩码值,则b.mask为真。当您为遮罩的值指定一个新值时,您正在取消遮罩它们,以便有效地使数组中的所有值有效,您可以使用b[np.invert(b.mask)]。在

所以这应该是有效的:

import numpy as np

a = np.ones(10000000, dtype=np.int64) * 500

mask = np.random.randint(0, 2, a.size)
b = np.ma.masked_array(a, mask=mask)

b[np.invert(b.mask)] = 1000
print(np.average(b), np.mean(b), np.ma.average(b), np.ma.mean(b))

它将为您提供除np.average之外的正确值。在

除此之外,当你得到负/不正确的值时,这是因为你得到了一个整数溢出。使用dtype=np.int64应该可以解决这个问题

Edit:另一个选择是使用带有dtype=object的Python整数,而不是固定宽度的整数,但是这样做会比较慢,这个更改会使np.average崩溃,但其余方法都能正常工作。在

编辑2:在这种情况下,没有必要增加数组元素的大小,我们可以调用np.mean(b, dtype=np.float64),这样np.mean使用更大的累加器来避免溢出。在

相关问题 更多 >