首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在numpy数组上映射函数的最有效方法

在numpy数组上映射函数的最有效方法
EN

Stack Overflow用户
提问于 2016-02-05 10:08:11
回答 7查看 724.1K关注 0票数 517

在numpy数组上映射函数的最有效方法是什么?在我目前的项目中,我一直在这样做:

代码语言:javascript
复制
import numpy as np 

x = np.array([1, 2, 3, 4, 5])

# Obtain array of square of each element in x
squarer = lambda t: t ** 2
squares = np.array([squarer(xi) for xi in x])

但是,这似乎非常低效,因为在将新数组转换回numpy数组之前,我使用列表理解将新数组构造为Python列表。

我们能做得更好吗?

EN

回答 7

Stack Overflow用户

发布于 2016-02-05 10:29:38

使用numpy.vectorize怎么样?

代码语言:javascript
复制
import numpy as np
x = np.array([1, 2, 3, 4, 5])
squarer = lambda t: t ** 2
vfunc = np.vectorize(squarer)
vfunc(x)
# Output : array([ 1,  4,  9, 16, 25])
票数 186
EN

Stack Overflow用户

发布于 2016-02-05 12:36:05

TL;DR

正如@user2357112所指出的,应用函数的“直接”方法始终是在Numpy数组上映射函数的最快、最简单的方法:

代码语言:javascript
复制
import numpy as np
x = np.array([1, 2, 3, 4, 5])
f = lambda x: x ** 2
squares = f(x)

通常避免使用np.vectorize,因为它的性能不是很好,并且有(或曾经)了许多issues。如果您正在处理其他数据类型,则可能需要研究如下所示的其他方法。

方法的比较

这里有一些简单的测试来比较三种映射函数的方法,本例使用Python3.6和NumPy 1.15.4。首先,用于测试的设置函数:

代码语言:javascript
复制
import timeit
import numpy as np

f = lambda x: x ** 2
vf = np.vectorize(f)

def test_array(x, n):
    t = timeit.timeit(
        'np.array([f(xi) for xi in x])',
        'from __main__ import np, x, f', number=n)
    print('array: {0:.3f}'.format(t))

def test_fromiter(x, n):
    t = timeit.timeit(
        'np.fromiter((f(xi) for xi in x), x.dtype, count=len(x))',
        'from __main__ import np, x, f', number=n)
    print('fromiter: {0:.3f}'.format(t))

def test_direct(x, n):
    t = timeit.timeit(
        'f(x)',
        'from __main__ import x, f', number=n)
    print('direct: {0:.3f}'.format(t))

def test_vectorized(x, n):
    t = timeit.timeit(
        'vf(x)',
        'from __main__ import x, vf', number=n)
    print('vectorized: {0:.3f}'.format(t))

使用五个元素进行测试(从快到慢排序):

代码语言:javascript
复制
x = np.array([1, 2, 3, 4, 5])
n = 100000
test_direct(x, n)      # 0.265
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.865
test_vectorized(x, n)  # 2.906

有100个元素:

代码语言:javascript
复制
x = np.arange(100)
n = 10000
test_direct(x, n)      # 0.030
test_array(x, n)       # 0.501
test_vectorized(x, n)  # 0.670
test_fromiter(x, n)    # 0.883

并且具有上千个或更多的阵列元素:

代码语言:javascript
复制
x = np.arange(1000)
n = 1000
test_direct(x, n)      # 0.007
test_fromiter(x, n)    # 0.479
test_array(x, n)       # 0.516
test_vectorized(x, n)  # 0.945

不同版本的Python/NumPy和编译器优化会有不同的结果,所以针对您的环境进行类似的测试。

票数 101
EN

Stack Overflow用户

发布于 2016-02-05 10:36:17

代码语言:javascript
复制
squares = squarer(x)

数组上的算术操作是以元素为单位自动应用的,具有高效的C级循环,避免了适用于Python级循环或理解的所有解释器开销。

您希望应用于NumPy数组元素的大多数函数都将正常工作,尽管有些函数可能需要更改。例如,if不能以元素的方式工作。您可能希望将它们转换为使用像numpy.where这样的结构

代码语言:javascript
复制
def using_if(x):
    if x < 5:
        return x
    else:
        return x**2

变成了

代码语言:javascript
复制
def using_where(x):
    return numpy.where(x < 5, x, x**2)
票数 37
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35215161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档