【问题标题】:What is an efficient way to calculate the mean of values in the bin with maximum frequency for large number of numpy arrays?对于大量 numpy 数组,计算具有最大频率的 bin 中值的平均值的有效方法是什么?
【发布时间】:2021-08-23 04:53:54
【问题描述】:

我正在寻找一种有效的方法来对数百万个数组进行以下计算。对于每个数组中的值,我想计算 bin 中频率最高的值的平均值,如下所示。一些数组可能包含 nan 值,而其他值是浮点数。我的实际数据的循环需要很长时间才能完成。

import numpy as np

array = np.array([np.random.uniform(0, 10) for i in range(800,)])

# adding nan values
mask = np.random.choice([1, 0], array.shape, p=[.7, .3]).astype(bool)
array[mask] = np.nan

array = array.reshape(50, 16)

bin_values=np.linspace(0, 10, 21)

f = np.apply_along_axis(lambda a: np.histogram(a, bins=bin_values)[0], 1, array) 

bin_start = np.apply_along_axis(lambda a: bin_values[np.argmax(a)], 1, f).reshape(array.shape[0], -1)
bin_end = bin_start + (abs(bin_values[1]-bin_values[0])

values = np.zeros(array.shape[0])

for i in range(array.shape[0]):
    values[i] = np.nanmean(array[i][(array[i]>=bin_start[i])*(array[i]<bin_end[i])])

另外,当我运行上述代码时,我收到三个警告。第一个是我计算 value 变量的行的“RuntimeWarning:空切片的平均值”。我设置了一个条件,以防我有所有 nan 值来跳过这一行,但警告并没有消失。我想知道这是什么原因。另外两个警告是针对不满足 less 和 greater_equal 条件的情况,这对我来说是有意义的,因为它们可能是 nan 值。

【问题讨论】:

标签: python numpy histogram frequency bins


【解决方案1】:

我想在其上运行此算法的数组是独立的,但我已经使用 12 个单独的脚本来处理它们。并行运行代码是一种选择,但是,现在我希望改进算法本身。

我使用 lambda 函数的原因是在轴上运行 numpy.histogram,因为直方图函数似乎没有将轴作为选项。我能够使用掩码并从代码中删除循环。代码现在快了 2 倍,但我认为它仍然可以进一步改进。

我可以通过一个例子更详细地解释我想要做什么,如果它澄清它。想象一下,我有 36 个大于 0 且小于 20 的数字。此外,我在相同的间隔(0.0_0.5、0.5_1.0、1.0_1.5、...、19.5_20)上具有相等距离为 0.5 的 bin。 0)。我想看看我是否将这 36 个数字放入它们对应的 bin 中,其中包含最多数字的 bin 中的数字的平均值是多少。

如果您能想到更快的算法,请发布您的解决方案。

import numpy as np

# creating an array to test the algorithm

array = np.array([np.random.uniform(0, 10) for i in range(800,)])

# adding nan values
mask = np.random.choice([1, 0], array.shape, p=[.7, .3]).astype(bool)
array[mask] = np.nan

array = array.reshape(50, 16)

# the algorithm

bin_values=np.linspace(0, 10, 21)
    
# calculating the frequency of each bin
f = np.apply_along_axis(lambda a: np.histogram(a, bins=bin_values)[0], 1, array) 

bin_start = np.apply_along_axis(lambda a: bin_values[np.argmax(a)], 1, f).reshape(array.shape[0], -1)
bin_end = bin_start + (abs(bin_values[1]-bin_values[0]))

# creating a mask to get the mean over the bin with maximum frequency
mask = (array>=bin_start) * (array<bin_end)

mask_nan = np.tile(np.nan, (mask.shape[0], mask.shape[1]))

mask_nan[mask] = 1

v = np.nanmean(array * mask_nan, axis = 1)

【讨论】:

    猜你喜欢
    • 2022-11-12
    • 2021-06-06
    • 2011-03-23
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 2016-08-24
    • 2019-07-31
    • 2022-01-27
    相关资源
    最近更新 更多