我有一个由np.uint64组成的Numy数组,其中只包含01值,我必须将0映射到np.float64(1.0),并将1映射到np.float64(-1.0).

因为解释器不知道它只需要转换01,所以它使用了代价高昂的通用算法,所以我想使用一个带有结果的数组,并使用uint64作为数组的索引,避免了任何转换,但它更慢.

import numpy as np
import timeit


random_bit = np.random.randint(0, 2, size=(10000), dtype=np.uint64)


def np_cast(random_bit):
    vectorized_result = 1.0 - 2.0 * np.float64(random_bit)
    return vectorized_result


def product(random_bit):
    mapped_result = 1.0 - 2.0 * random_bit
    return mapped_result


np_one_minus_one = np.array([1.0, -1.0]).astype(np.float64)


def _array(random_bit):
    mapped_result = np_one_minus_one[random_bit]
    return mapped_result


one = np.float64(1)
minus_two = np.float64(-2)


def astype(random_bit):
    mapped_result = one + minus_two * random_bit.astype(np.float64)
    return mapped_result


function_list = [np_cast, product, _array, astype]

print("start benchmark")
for function in function_list:
    _time = timeit.timeit(lambda: function(random_bit), number=100000)
    print(f"{function.__name__}: {_time:.3f} seconds")

我有过这样的经历:

np_cast: 178.604 seconds
product: 172.939 seconds
_array: 239.305 seconds
astype: 186.031 seconds

推荐答案

通过使用numba,您可以将此操作速度提高约4倍,对于一般ND情况,这可能是:

import numba as nb

@nb.vectorize
def numba_if(random_bit):
    return -1.0 if random_bit else 1.0

@nb.vectorize
def numba_product(random_bit):
    return 1.0 - 2.0 * random_bit

或者在您的特定1D情况下,您可以使用显式循环来加快速度:

import numpy as np

@nb.njit
def numba_if_loop(random_bit):
    assert random_bit.ndim == 1
    result = np.empty_like(random_bit, dtype=np.float64)
    for i in range(random_bit.size):
        result[i] = -1.0 if random_bit[i] else 1.0
    return result

@nb.njit
def numba_product_loop(random_bit):
    assert random_bit.ndim == 1
    result = np.empty_like(random_bit, dtype=np.float64)
    for i in range(random_bit.size):
        result[i] = 1.0 - 2.0 * random_bit[i]
    return result

计时( comments 中的mason相当于lambda x:(1-2*x.astype(np.int8)).astype(float)):

%timeit np_cast(random_bit)
%timeit product(random_bit)
%timeit _array(random_bit)
%timeit astype(random_bit)
%timeit mason(random_bit)

assert np.array_equal(np_cast(random_bit), numba_if(random_bit))
assert np.array_equal(np_cast(random_bit), numba_product(random_bit))
assert np.array_equal(np_cast(random_bit), numba_if_loop(random_bit))
assert np.array_equal(np_cast(random_bit), numba_product_loop(random_bit))

%timeit numba_if(random_bit)
%timeit numba_product(random_bit)
%timeit numba_if_loop(random_bit)
%timeit numba_product_loop(random_bit)

输出:

6.58 µs ± 218 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
7.58 µs ± 251 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
11 µs ± 9.34 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
7.32 µs ± 674 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
6.86 µs ± 153 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.89 µs ± 25.8 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
2.07 µs ± 13.1 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
1.6 µs ± 14.7 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)
1.78 µs ± 5.31 ns per loop (mean ± std. dev. of 7 runs, 1,000,000 loops each)

Python相关问答推荐

在Python中是否可以输入使用任意大小参数列表的第一个元素的函数

在Python中使用readline函数时如何向下行

根据多列和一些条件创建新列

是否有方法将现有的X-Y图转换为X-Y-Y1图(以重新填充)?

Polars -转换为PL后无法计算熵.列表

已删除的构造函数调用另一个构造函数

将numpy矩阵映射到字符串矩阵

有条件地采样我的大型DF的最有效方法

如何根据条件在多指标框架上进行groupby

如何自动抓取以下CSV

如何比较numPy数组中的两个图像以获取它们不同的像素

从numpy数组和参数创建收件箱

Python库:可选地支持numpy类型,而不依赖于numpy

如何让程序打印新段落上的每一行?

大小为M的第N位_计数(或人口计数)的公式

根据二元组列表在pandas中创建新列

django禁止直接分配到多对多集合的前端.使用user.set()

我如何使法国在 map 中完全透明的代码?

多指标不同顺序串联大Pandas 模型

Django RawSQL注释字段