帮我消除python中的for循环

时间:2009-07-31 03:07:00

标签: python for-loop

必须有一种更快的方法。

这里有很多事情要做,但打开包装相当简单。

这是相关的python代码(来自scipy import *)

for i in arange(len(wav)):
    result[i] = sum(laser_flux * exp(-(wav[i] - laser_wav)**2) )

有一堆数组。

  • result - 长度数组(wav)
  • laser_flux - 长度数组(激光)
  • wav - 长度数组(wav)
  • laser_wav - 长度(激光)阵列

是的,在指数范围内,我正在逐个(逐个元素)平方标量值和laser_wav数组之间的差异。

一切都按预期工作(包括慢慢地)任何可以帮助我消除这个for循环的帮助将非常感激!

4 个答案:

答案 0 :(得分:13)

您将要使用Numpy数组(如果您还没有)来存储数据。然后,您可以利用np.newaxis进行阵列广播。对于wav中的每个值,您需要计算该值与laser_wav中每个值之间的差异。这表明您需要一个二维数组,其中两个维度为wav维度和laser维度。

在下面的示例中,我将选择第一个索引作为laser索引,将第二个索引选择为wav索引。使用样本数据,这将成为:

import numpy as np

LASER_LEN  = 5
WAV_LEN    = 10
laser_flux = np.arange(LASER_LEN)
wav        = np.arange(WAV_LEN)
laser_wav  = np.array(LASER_LEN)

# Tile wav into LASER_LEN rows and tile laser_wav into WAV_LEN columns
diff    = wav[np.newaxis,:] - laser_wav[:,np.newaxis]
exp_arg = -diff ** 2
sum_arg = laser_flux[:,np.newaxis] * np.exp(exp_arg)

# Now, the resulting array sum_arg should be of size (LASER_LEN,WAV_LEN)
# Since your original sum was along each element of laser_flux/laser_wav, 
# you'll need to sum along the first axis.
result = np.sum(sum_arg, axis=0)

当然,您可以将其简化为一个声明:

result = np.sum(laser_flux[:,np.newaxis] * 
                np.exp(-(wav[np.newaxis,:]-laser_wav[:,np.newaxis])**2),axis=0)

编辑:

正如对问题的评论中所指出的,你可以利用线性代数风格乘法定义中固有的“乘法和”。然后变成:

result = np.dot(laser_flux, 
    np.exp(-(wav[np.newaxis,:] - laser_wav[:,np.newaxis])**2))

答案 1 :(得分:2)

我是Python新手,所以这可能不是Python中最优秀的 ,但我会对Perl,Scheme等使用相同的技术。

def func(x):
    delta = x - laser_wav
    return sum(laser_flux * exp(-delta * delta))
result = map(func, wav)

答案 2 :(得分:1)

如果原始性能存在问题,您可能会受益于重写以利用多个核心(如果您拥有它们)。

from multiprocessing import Pool
p = Pool(5) # about the number of cores you have

def f(i):
    delta = wav[i] - laser_wav
    return sum(laser_flux * exp(-delta*delta) )

result = p.map(f, arange(len(wav)) )

答案 3 :(得分:0)

首先,将变量本身乘以使用**幂运算符似乎稍快一些:

~$ python -m timeit -n 100000 -v "x = 4.1; x * x"
raw times: 0.0904 0.0513 0.0493
100000 loops, best of 3: 0.493 usec per loop
~$ python -m timeit -n 100000 -v "x = 4.1; x**2"
raw times: 0.101 0.147 0.118
100000 loops, best of 3: 1.01 usec per loop