Python 将函数应用于数据数组的0维 问题
我有一个Python 将函数应用于数据数组的0维 问题,python,function,numpy,multidimensional-array,vectorization,Python,Function,Numpy,Multidimensional Array,Vectorization,我有一个ndarray,由arr定义,它是一个n维立方体,每个维的长度m 我想通过沿维度n=0切片,并将每个n-1-dim切片作为函数的输入,来执行函数func 这似乎适用于map(),但我找不到合适的numpy变体
ndarray
,由arr
定义,它是一个n
维立方体,每个维的长度m
n=0
切片,并将每个n-1
-dim切片作为函数的输入,来执行函数func
map()
,但我找不到合适的numpy
变体<矢量化似乎将n-1
-张量拆分为单个标量项。无论是沿_轴应用
还是在_轴上应用
似乎都不合适
我的问题是,我需要将任意函数作为输入传递,因此我认为einsum
的解决方案也不可行
问题:
- 您知道使用
np.asarray(map(func,arr))的最佳
替代方法吗numpy
arr
定义为4
-dim立方体(或4-张量):
我定义了一个示例函数f
def f(x):
"""makes it obvious how the np.ndarray is being passed into the function"""
try: # perform an op using x[0,0,0] which is expected to exist
i = x[0,0,0]
except:
print '\nno element x[0,0,0] in x: \n{}'.format(x)
return np.nan
return x-x+i
此函数的预期结果,res
,将保持相同的形状,但将满足以下要求:
print all([(res[i] == i*m**(n-1)).all() for i in range(m)])
这适用于默认的map()
函数
res = np.asarray(map(f, a))
print all([(res[i] == i*m**(n-1)).all() for i in range(m)])
True
我希望np.vectorize
的工作方式与map()
相同,但它在标量条目中起作用:
res = np.vectorize(f)(a)
no element x[0,0,0] in x:
0
...
考虑到
arr
是4d,并且您的fn
可以在3d阵列上工作
np.asarray(map(func, arr))
看起来非常合理。我会使用列表理解表单,但这是编程风格的问题
np.asarray([func(i) for i in arr])
for i in arr
在arr
的第一个维度上迭代。实际上,它将arr
视为3d阵列的列表。然后它将结果列表重新组合成4d数组
np.vectorize
doc可以更明确地说明使用标量的函数。但是是的,它将值作为标量传递。请注意,np.vectorize
没有传递迭代轴参数的规定。当函数从多个数组中获取值时,它最有用,例如
[func(a,b) for a,b in zip(arrA, arrB)]
它概括了zip
,因此允许广播。但除此之外,它是一个迭代的解决方案。它对func
的本质一无所知,因此无法加快调用速度
np.vectorize
最终调用了np.frompyfunc
,它的通用性稍差,速度稍快。但它也将标量传递给func
np.沿/在ax(e/i)上应用
也在一个或多个轴上迭代。你可能会发现他们的代码很有启发性,但我同意他们不适用于这里
map方法的一种变体是分配结果数组和索引:
In [45]: res=np.zeros_like(arr,int)
In [46]: for i in range(arr.shape[0]):
...: res[i,...] = f(arr[i,...])
如果需要在与第一个轴不同的轴上迭代,这可能会更容易
你需要自己计时,看看哪个更快
========================
在第一个维度上进行迭代并进行就地修改的示例:
In [58]: arr.__array_interface__['data'] # data buffer address
Out[58]: (152720784, False)
In [59]: for i,a in enumerate(arr):
...: print(a.__array_interface__['data'])
...: a[0,0,:]=i
...:
(152720784, False) # address of the views (same buffer)
(152720892, False)
(152721000, False)
In [60]: arr
Out[60]:
array([[[[ 0, 0, 0],
[ 3, 4, 5],
[ 6, 7, 8]],
...
[[[ 1, 1, 1],
[30, 31, 32],
...
[[[ 2, 2, 2],
[57, 58, 59],
[60, 61, 62]],
...]]])
当我迭代一个数组时,我得到一个从公共数据缓冲区上的连续点开始的视图。如果我修改视图,如上所述,甚至使用
a[:]=…
,我会修改原始视图。我不必写任何回信。但是不要使用a=..
,这会断开与原始数组的链接。相关但没有解决问题:map()的问题
和生成器表达式是为ndarray
重新分配内存位置,这对于大型数组是浪费的-我希望有一个numpy
函数,它只使用现有内存指针指向当前数组位置arr[I,]=f(arr[I,…)
将子阵列放回原始阵列中。是否创建临时数组、副本或视图取决于f
正在执行的操作的详细信息。但是我想知道你对numpy数组中内存指针的使用有多了解。谢谢你的提示!我想说,我比大多数python专家都更了解,但可能是平均水平较低——这让我了解了大部分情况,特别是第2.3节和第3.1.1节,我将尝试编写一个f
的示例,该示例修改其输入x
,而不是最后一个赋值。谢谢-我正在处理大小为48**4
或甚至48**7
的晶格,但后者我可能会使用C
或Fortran
所以内存使用是值得考虑的,即使它只是我代码中的一条注释作为提醒
In [58]: arr.__array_interface__['data'] # data buffer address
Out[58]: (152720784, False)
In [59]: for i,a in enumerate(arr):
...: print(a.__array_interface__['data'])
...: a[0,0,:]=i
...:
(152720784, False) # address of the views (same buffer)
(152720892, False)
(152721000, False)
In [60]: arr
Out[60]:
array([[[[ 0, 0, 0],
[ 3, 4, 5],
[ 6, 7, 8]],
...
[[[ 1, 1, 1],
[30, 31, 32],
...
[[[ 2, 2, 2],
[57, 58, 59],
[60, 61, 62]],
...]]])