繁体   English   中英

如何将 NumPy 数组按元素舍入到第一个非零数字?

[英]How to do element-wise rounding of NumPy array to first non-zero digit?

我想通过以下方式“舍入”(不精确的数学舍入)numpy 数组的元素:

给定一个 numpy NxN 或 NxM 二维数组,数字在 0.00001 到 9.99999 之间,例如

 a=np.array([[1.232, 1.872,2.732,0.123],
             [0.0019, 0.025, 1.854, 0.00017],
             [1.457, 0.0021, 2.34 , 9.99],
             [1.527, 3.3, 0.012 , 0.005]]
    )

我想基本上通过选择每个元素的第一个非零数字(不管第一个非零数字后面的数字)来“舍入”这个 numpy 数组,给出 output:

output =np.array([[1.0, 1.0, 2.0, 0.1],
                 [0.001, 0.02, 1.0, 0.0001],
                 [1.0, 0.002, 2 , 9.0],
                 [1, 3, 0.01 , 0.005]]
        )

谢谢你的帮助!

您可以使用np.logspacenp.seachsorted来确定每个元素的数量级,然后除以并乘回

po10 = np.logspace(-10,10,21)
oom = po10[po10.searchsorted(a)-1]
a//oom*oom
# array([[1.e+00, 1.e+00, 2.e+00, 1.e-01],
#        [1.e-03, 2.e-02, 1.e+00, 1.e-04],
#        [1.e+00, 2.e-03, 2.e+00, 9.e+00],
#        [1.e+00, 3.e+00, 1.e-02, 5.e-03]])

您想要做的是保留固定数量的有效数字

此功能未集成到 NumPy 中。

要仅获得 1 个有效数字,您可以查看@PaulPanzer@darcamo答案(假设您只有正值)。

如果您想要使用指定数量的有效数字的东西,您可以使用类似的东西:

def significant_figures(arr, num=1):
    # : compute the order of magnitude
    order = np.zeros_like(arr)  
    mask = arr != 0
    order[mask] = np.floor(np.log10(np.abs(arr[mask])))
    del mask  # free unused memory
    # : compute the corresponding precision
    prec = num - order - 1
    return np.round(arr * 10.0 ** prec) / 10.0 ** prec


print(significant_figures(a, 1))
# [[1.e+00 2.e+00 3.e+00 1.e-01]
#  [2.e-03 2.e-02 2.e+00 2.e-04]
#  [1.e+00 2.e-03 2.e+00 1.e+01]
#  [2.e+00 3.e+00 1.e-02 5.e-03]]

print(significant_figures(a, 2))
# [[1.2e+00 1.9e+00 2.7e+00 1.2e-01]
#  [1.9e-03 2.5e-02 1.9e+00 1.7e-04]
#  [1.5e+00 2.1e-03 2.3e+00 1.0e+01]
#  [1.5e+00 3.3e+00 1.2e-02 5.0e-03]]

编辑

对于截断的 output 在return之前使用np.floor()而不是np.round()

首先获得数组中每个数字的 10 的幂

powers = np.floor(np.log10(a))

在您的示例中,这给了我们

array([[ 0.,  0.,  0., -1.],
       [-3., -2.,  0., -4.],
       [ 0., -3.,  0.,  0.],
       [ 0.,  0., -2., -3.]])

现在,如果我们将数组中的第i个元素除以10**power_i ,我们实际上将数组中的每个数字非零元素移动到第一个 position。 现在我们可以简单地删除其他非零数字,然后将结果乘以10**power_i以回到原始比例。

完整的解决方案只有下面的代码

powers = np.floor(np.log10(a))
10**powers * np.floor(a/10**powers)

大于或等于 10 的数字呢?

为此,您可以简单地获取数组中原始值的np.floor 我们可以用面具轻松做到这一点。 您可以修改答案如下

powers = np.floor(np.log10(a))
result = 10**powers * np.floor(a/10**powers)

mask = a >= 10
result[mask] = np.floor(a[mask])

您还可以使用掩码来避免计算稍后将被替换的数字的幂和对数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM