【发布时间】:2023-03-10 21:58:01
【问题描述】:
我有一个 rank-1 numpy.array 我想制作一个箱线图。但是,我想排除数组中所有等于零的值。目前,我通过循环数组来解决这个问题,如果不等于零,则将值复制到一个新数组中。但是,由于数组包含 86 000 000 个值,而且我必须多次这样做,这需要很大的耐心。
有没有更智能的方法来做到这一点?
【问题讨论】:
标签: python arrays numpy filtering
我有一个 rank-1 numpy.array 我想制作一个箱线图。但是,我想排除数组中所有等于零的值。目前,我通过循环数组来解决这个问题,如果不等于零,则将值复制到一个新数组中。但是,由于数组包含 86 000 000 个值,而且我必须多次这样做,这需要很大的耐心。
有没有更智能的方法来做到这一点?
【问题讨论】:
标签: python arrays numpy filtering
[i for i in Array if i != 0.0] 如果数字是浮点数
或 [i for i in SICER if i != 0] 如果数字是整数。
【讨论】:
[i for i in Array if i > 0]
我决定比较这里提到的不同方法的运行时间。为此,我使用了我的库 simple_benchmark。
array[array != 0] 的布尔索引似乎是最快(也是最短)的解决方案。
对于较小的数组,与其他方法相比,MaskedArray 方法非常慢,但与布尔索引方法一样快。但是对于中等大小的数组,它们之间并没有太大区别。
这是我使用的代码:
from simple_benchmark import BenchmarkBuilder
import numpy as np
bench = BenchmarkBuilder()
@bench.add_function()
def boolean_indexing(arr):
return arr[arr != 0]
@bench.add_function()
def integer_indexing_nonzero(arr):
return arr[np.nonzero(arr)]
@bench.add_function()
def integer_indexing_where(arr):
return arr[np.where(arr != 0)]
@bench.add_function()
def masked_array(arr):
return np.ma.masked_equal(arr, 0)
@bench.add_arguments('array size')
def argument_provider():
for exp in range(3, 25):
size = 2**exp
arr = np.random.random(size)
arr[arr < 0.1] = 0 # add some zeros
yield size, arr
r = bench.run()
r.plot()
【讨论】:
在这种情况下,您想使用掩码数组,它会保持数组的形状,并且会被所有 numpy 和 matplotlib 函数自动识别。
X = np.random.randn(1e3, 5)
X[np.abs(X)< .1]= 0 # some zeros
X = np.ma.masked_equal(X,0)
plt.boxplot(X) #masked values are not plotted
#other functionalities of masked arrays
X.compressed() # get normal array with masked values removed
X.mask # get a boolean array of the mask
X.mean() # it automatically discards masked values
您可以使用布尔数组进行索引。对于 NumPy 数组A:
res = A[A != 0]
你可以像上面那样使用Boolean array indexing,bool类型转换,np.nonzero,或者np.where。以下是一些性能基准测试:
# Python 3.7, NumPy 1.14.3
np.random.seed(0)
A = np.random.randint(0, 5, 10**8)
%timeit A[A != 0] # 768 ms
%timeit A[A.astype(bool)] # 781 ms
%timeit A[np.nonzero(A)] # 1.49 s
%timeit A[np.where(A)] # 1.58 s
【讨论】:
一行简单的代码就可以得到一个排除所有“0”值的数组:
np.argwhere(*array*)
示例:
import numpy as np
array = [0, 1, 0, 3, 4, 5, 0]
array2 = np.argwhere(array)
print array2
[1, 3, 4, 5]
【讨论】:
我建议您在这种情况下简单地使用NaN,在这种情况下,您希望忽略一些值,但仍希望保持过程统计尽可能有意义。所以
In []: X= randn(1e3, 5)
In []: X[abs(X)< .1]= NaN
In []: isnan(X).sum(0)
Out[: array([82, 84, 71, 81, 73])
In []: boxplot(X)
【讨论】:
a 其中a[k] 是一个NumPy 数组所以我想做[a[k][abs(a[k])<.1]=float('NaN') for k in data] 但这似乎在循环中失败了,而只有在循环中执行命令似乎工作...
for k in data: a[k][abs(a[k])< .1]= NaN ?
对于 NumPy 数组 a,可以使用
a[a != 0]
提取不等于零的值。
【讨论】:
a 具有更高的维度,则结果将是一个扁平的(一维)数组。也可以删除全为零的列或行。
a 是np.array。这不适用于内置的 python 数组。