同时迭代两个大数组

3

我需要遍历两个1000x1000的数组。我已经将分辨率降低到了100x100,以使迭代更快,但仍需大约15分钟才能完成一个数组的迭代!因此,我尝试同时遍历两个数组,发现以下方法:

for index, (x,y) in ndenumerate(izip(x_array,y_array)):

但是我遇到了错误:
ValueError: too many values to unpack

以下是完整的Python代码:我希望你能帮助我使它执行更快,因为这是我的硕士论文,最终我需要运行它大约100次...

area_length=11
d_circle=(area_length-1)/2

xdis_new=xdis.copy()
ydis_new=ydis.copy()
ie,je=xdis_new.shape


while (np.isnan(np.sum(xdis_new))) and (np.isnan(np.sum(ydis_new))):
xdis_interpolated=xdis_new.copy()
ydis_interpolated=ydis_new.copy()
# itx=np.nditer(xdis_new,flags=['multi_index'])
# for x in itx:
    # print 'next x and y'
for index, (x,y) in ndenumerate(izip(xdis_new,ydis_new)):
    if np.isnan(x):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=xdis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            xdis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    if np.isnan(y):
        print 'index',index[0],index[1]
        print 'interpolate'
        # define indizes of interpolation area
        i1=index[0]-(area_length-1)/2
        if i1<0:
            i1=0
        i2=index[0]+((area_length+1)/2)
        if i2>ie:
            i2=ie
        j1=index[1]-(area_length-1)/2
        if j1<0:
            j1=0
        j2=index[1]+((area_length+1)/2)
        if j2>je:
            j2=je
        # -->
        print 'i1',i1,'','i2',i2
        print 'j1',j1,'','j2',j2

        area_values=ydis_new[i1:i2,j1:j2]
        print area_values

        b=area_values[~np.isnan(area_values)]

        if len(b)>=((area_length-1)/2)*4:

            xi,yi=meshgrid(arange(len(area_values[0,:])),arange(len(area_values[:,0])))

            weight=zeros((len(area_values[0,:]),len(area_values[:,0])))
            d=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weight_fac=zeros((len(area_values[0,:]),len(area_values[:,0])))
            weighted_area=zeros((len(area_values[0,:]),len(area_values[:,0])))

            d=sqrt((xi-xi[(area_length-1)/2,(area_length-1)/2])*(xi-xi[(area_length-1)/2,(area_length-1)/2])+(yi-yi[(area_length-1)/2,(area_length-1)/2])*(yi-yi[(area_length-1)/2,(area_length-1)/2]))
            weight=1/d
            weight[where(d==0)]=0
            weight[where(d>d_circle)]=0
            weight[where(np.isnan(area_values))]=0

            weight_sum=np.sum(weight.flatten())
            weight_fac=weight/weight_sum
            weighted_area=area_values*weight_fac

            print 'weight'
            print weight_fac
            print 'values'
            print area_values
            print 'weighted'
            print weighted_area

            m=nansum(weighted_area)
            ydis_interpolated[index]=m
            print 'm',m

        else:
            print 'insufficient elements'

    else:
        print 'no need to interpolate'

xdis_new=xdis_interpolated
ydis_new=ydis_interpolated

对于那些不了解的人 - izip() 是来自itertools模块的:from itertools import izp - Pierz
5个回答

2

您特别要求在单个循环中迭代两个数组。以下是一种方法:

l1 = ["abc", "def", "hi"]
l2 = ["ghi", "jkl", "lst"]
for f,s in zip(l1,l2):
    print "%s : %s" %(f,s)

以上内容适用于Python 3,您可以在Python 2中使用izip。

2

一些建议:

  • 对代码进行性能分析,看看哪部分最慢。可能不是迭代本身,而是每次需要进行的计算。
  • 尽量减少函数调用。在Python中,函数调用并非免费。
  • 将最慢的部分重写为C扩展,然后在Python代码中调用该C函数(请参见扩展和嵌入Python解释器)。
  • 此页面也有一些好的建议。

1

您可以使用以下代码作为您的for循环:

for index, x in ndenumerate((x_array,y_array)):

但这并不能帮助您太多,因为您的计算机无法同时执行两个任务。


0

评论 #1:你不想在 izip 迭代器上使用 ndenumerate,因为它会输出迭代器,这不是你想要的。

评论 #2:

i1=index[0]-(area_length-1)/2
if i1<0:
    i1=0

可以在i1 = min(index[0] - (area_length - 1) / 2, 0)中进行简化,您可以将(area_length +/- 1) / 2存储在特定的变量中。

想法#1:尝试对数组的平面版本进行迭代,例如使用以下方法:

for (i, (x, y)) in enumerate(izip(xdis_new.flat,ydis_new.flat)): 

你可以通过 divmod(i, xdis_new.shape[-1]) 获取原始索引,因为你应该首先按行迭代。

想法 #2:仅在 nans 上迭代,即使用 np.isnan(xdis_new)|np.isnan(ydis_new) 索引你的数组,这可以节省一些迭代次数。

编辑 #1

  • 你可能不需要在循环中初始化 dweight_facweighted_area,因为你单独计算它们。

  • 你的 weight[where(d>0)] 可以简化为 weight[d>0]

  • 你需要 weight_fac 吗?你不能只计算 weight 然后在原地归一化吗?这应该可以节省一些临时数组。


你的评论和想法听起来非常不错!我已经考虑过将数组压平,但是我正好遇到了获取原始索引的问题,所以非常感谢你!我会尝试你所说的,然后我们看看... =) - Melanie Maza
我在divmod这个函数上遇到了问题...我将它放在for循环后面,但是出现了错误:TypeError: unsupported operand type(s) for divmod(): 'tuple' and 'int' 你能告诉我如何在哪里使用这个函数吗?谢谢! - Melanie Maza
好的,我想我有一个divmod函数的答案... [链接](https://dev59.com/Amkx5IYBdhLWcg3wCP-Y)看起来可以工作... - Melanie Maza
你可以尝试这样做:[(i,j,x,y) for ((i,j),x,y) in zip(zip(*np.unravel_index(np.arange(np.multiply(*X.shape)),X.shape)),X.flat,Y.flat)] - Pierre GM

0

性能分析绝对是一个很好的开始,可以确定时间都花在了哪里。

我通常使用cProfile模块,因为它需要最小的开销并提供了足够的信息。

import cProfile
import pstats
cProfile.run('main()', "ProfileData.txt", 'tottime')
p = pstats.Stats('ProfileData.txt')   
p.sort_stats('cumulative').print_stats(100)

在你的例子中,你需要将你的代码放入一个 main() 函数中,才能在文件末尾使用这段代码片段。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接