gpt4 book ai didi

python - 通过移动索引移动二维数组中的数据

转载 作者:行者123 更新时间:2023-11-28 17:37:27 25 4
gpt4 key购买 nike

我需要移动一个二维数组字段,即我有一个“previous_data”数组,我通过移动索引访问它以创建我的“new_data”数组。

我可以在非 Pythonic(且速度较慢)的循环中执行此操作,但非常感谢您帮助我找到 Pythonic(且更快)的解决方案!

非常感谢任何帮助和提示!

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import mpl

def nonpythonic():
#this works, but is slow (for large arrays)
new_data = np.zeros((ny,nx))
for j in xrange(ny):
for i in xrange(nx):
#go through each item, check if it is within the bounds
#and assign the data to the new_data array
i_new = ix[j,i]
j_new = iy[j,i]
if ((i_new>=0) and (i_new<nx) and (j_new>=0) and (j_new<ny)):
new_data[j,i]=previous_data[j_new,i_new]

ef, axar = plt.subplots(1,2)
im = axar[0].pcolor(previous_data, vmin=0,vmax=2)
ef.colorbar(im, ax=axar[0], shrink=0.9)
im = axar[1].pcolor(new_data, vmin=0,vmax=2)
ef.colorbar(im, ax=axar[1], shrink=0.9)

plt.show()

def pythonic():
#tried a few things here, but none are working
#-tried assigning NaNs to indices (ix,iy) which are out of bounds, but NaN's don't work for indices
#-tried masked arrays, but they also don't work as indices
#-tried boolean arrays, but ended in shape mismatches
#just as in the nonworking code below
ind_y_good = np.where(iy>=0) and np.where(iy<ny)
ind_x_good = np.where(ix>=0) and np.where(ix<nx)

new_data = np.zeros((ny,nx))

new_data[ind_y_good,ind_x_good] = previous_data[iy[ind_y_good],ix[ind_x_good]]

#some 2D array:
nx = 20
ny = 30
#array indices:
iy, ix = np.indices((ny,nx))
#modify indices (shift):
iy = iy + 1
ix = ix - 4
#create some out of range indices (which might happen in my real scenario)
iy[0,2:7] = -9999
ix[0:3,-1] = 6666

#some previous data which is the basis for the new_data:
previous_data = np.ones((ny,nx))
previous_data[2:8,10:20] = 2
nonpythonic()
pythonic()

这是上面的工作(非pythonic)代码的结果: nonpythonic working example of shifted data

最佳答案

我实现了 pythonic 的一个版本,它复制了 nonpythonic 并带有一些屏蔽和索引调整 - 见下文。顺便说一下,我认为"new"索引应该是对应于新数组的索引,而不是旧数组,但我将其保留在您现有的函数中。

要意识到的主要事情是,在你对问题的尝试中,你的条件

ind_y_good = np.where(iy>=0) and np.where(iy<ny)
ind_x_good = np.where(ix>=0) and np.where(ix<nx)

必须组合,因为我们必须始终有成对的 xy 索引。即,如果 x 索引无效,那么 y 也是无效的。

最后,如果索引真的全部移动了一个常数因子,您可以通过使用 NumPy 的 roll 函数并获取与有效区域对应的索引切片来使这更简单。

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import mpl


def nonpythonic(previous_data, ix, iy, nx, ny):
#this works, but is slow (for large arrays)
new_data = np.zeros((ny,nx))
for j in xrange(ny):
for i in xrange(nx):
#go through each item, check if it is within the bounds
#and assign the data to the new_data array
i_new = ix[j,i]
j_new = iy[j,i]
if ((i_new>=0) and (i_new<nx) and (j_new>=0) and (j_new<ny)):
new_data[j,i]=previous_data[j_new,i_new]

return new_data

def pythonic(previous_data, ix, iy):

ny, nx = previous_data.shape
iy_old, ix_old = np.indices(previous_data.shape)

# note you must apply the same condition to both
# index arrays
valid = (iy >= 0) & (iy < ny) & (ix >= 0) & (ix < nx)

new_data = np.zeros((ny,nx))

new_data[iy_old[valid], ix_old[valid]] = previous_data[iy[valid], ix[valid]]
return new_data


def main():
#some 2D array:
nx = 20
ny = 30
#array indices:
iy, ix = np.indices((ny,nx))
#modify indices (shift):
iy = iy + 1
ix = ix - 4
#create some out of range indices (which might happen in my real scenario)
iy[0,2:7] = -9999
ix[0:3,-1] = 6666

#some previous data which is the basis for the new_data:
previous_data = np.ones((ny,nx))
previous_data[2:8,10:20] = 2
data_nonpythonic = nonpythonic(previous_data, ix, iy, nx, ny)
data_pythonic = pythonic(previous_data, ix, iy)

new_data = data_nonpythonic
ef, axar = plt.subplots(1,2)
im = axar[0].pcolor(previous_data, vmin=0,vmax=2)
ef.colorbar(im, ax=axar[0], shrink=0.9)
im = axar[1].pcolor(new_data, vmin=0,vmax=2)
ef.colorbar(im, ax=axar[1], shrink=0.9)
plt.show()
print(np.allclose(data_nonpythonic, data_pythonic))

if __name__ == "__main__":
main()

关于python - 通过移动索引移动二维数组中的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29034227/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com