如何将 NumPy 数组按元素舍入到第一个非零数字?
How to do element-wise rounding of NumPy array to first non-zero digit?
我想 "round"(不是精确的数学舍入)以下方式的 numpy 数组的元素:
给定一个数字在 0.00001 到 9.99999 之间的 numpy NxN 或 NxM 二维数组,如
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]]
)
我基本上想 "round" 通过选择每个元素的第一个非零数字(不管第一个非零数字后面的数字)来 "round" 这个 numpy 数组
给出输出:
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.logspace
和np.seachsorted
来确定每个元素的数量级然后floor divide and multiply back
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]])
首先用
对数组中的每个数字求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
,我们实际上会将数组中的每个数字非零元素移动到第一个位置。现在我们可以简单地发言以删除其他非零数字,然后将结果乘以 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])
您也可以使用掩码来避免计算稍后将被替换的数字的幂和对数。
你想要做的是保持固定数量的 significant figures。
此功能未集成到 NumPy 中。
要仅获得 1 位有效数字,您可以查看 or 个答案(假设您只有正值)。
如果你想要一些有效数字有效的东西,你可以使用类似的东西:
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]]
编辑
对于截断的输出,在 return
.
之前使用 np.floor()
而不是 np.round()
我想 "round"(不是精确的数学舍入)以下方式的 numpy 数组的元素:
给定一个数字在 0.00001 到 9.99999 之间的 numpy NxN 或 NxM 二维数组,如
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]]
)
我基本上想 "round" 通过选择每个元素的第一个非零数字(不管第一个非零数字后面的数字)来 "round" 这个 numpy 数组 给出输出:
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.logspace
和np.seachsorted
来确定每个元素的数量级然后floor divide and multiply back
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]])
首先用
对数组中的每个数字求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
,我们实际上会将数组中的每个数字非零元素移动到第一个位置。现在我们可以简单地发言以删除其他非零数字,然后将结果乘以 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])
您也可以使用掩码来避免计算稍后将被替换的数字的幂和对数。
你想要做的是保持固定数量的 significant figures。
此功能未集成到 NumPy 中。
要仅获得 1 位有效数字,您可以查看
如果你想要一些有效数字有效的东西,你可以使用类似的东西:
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]]
编辑
对于截断的输出,在 return
.
np.floor()
而不是 np.round()