Python:对使用对象数组的函数调用进行矢量化
我有一个对象数组。我还有一个函数,一次需要来自两个对象的信息。我希望将对函数的调用矢量化,以便它一次计算所有调用,而不是使用循环遍历必需的一对对象 如果我用必要的数据创建一个数组,我就可以实现这一点。然而,这在一定程度上违背了使用对象的目的 这是代码。它目前使用数组方法工作,只需要在函数中注释/取消注释一行就可以切换到“object”模式,但我非常希望这样做 我得到的错误是:TypeError:只有包含一个元素的整数数组才能转换为索引Python:对使用对象数组的函数调用进行矢量化,python,arrays,python-3.x,numpy,vectorization,Python,Arrays,Python 3.x,Numpy,Vectorization,我有一个对象数组。我还有一个函数,一次需要来自两个对象的信息。我希望将对函数的调用矢量化,以便它一次计算所有调用,而不是使用循环遍历必需的一对对象 如果我用必要的数据创建一个数组,我就可以实现这一点。然而,这在一定程度上违背了使用对象的目的 这是代码。它目前使用数组方法工作,只需要在函数中注释/取消注释一行就可以切换到“object”模式,但我非常希望这样做 我得到的错误是:TypeError:只有包含一个元素的整数数组才能转换为索引 import numpy as np import time
import numpy as np
import time as time
class ExampleObject():
def __init__(self, r):
self.r = r
def ExampleFunction(x):
""" WHAT I REALLY WANT """
# answer = exampleList[x].r - exampleList[indexArray].r
"""WHAT I AM STUCK WITH """
answer = coords[x] - exampleList[indexArray].r
return answer
indexArray = 5 #arbitrary choice of array index
sizeArray = 1000
exampleList = []
for i in range(sizeArray):
r = np.random.rand()
exampleList.append( ExampleObject( r ) )
index_list = np.arange(0,sizeArray,1)
index_list = np.delete(index_list,indexArray)
coords = np.array([h.r for h in exampleList])
answerArray = ExampleFunction(index_list)
问题是,当我向函数传递一个整数数组时,当我使用对象数组(实际上是列表)时,它不会返回一个答案数组(我想要的向量化)。如果我使用数组(没有对象,每个元素中只有数据),它就可以工作。但正如我所说的,在我看来,这违背了存储对象信息的初衷。我真的需要在数组中存储相同的信息吗?我不能发表评论,很抱歉误用了答案部分 如果numpy数组的数据类型是python对象,则numpy数组的内存不连续。操作的矢量化可能不会大大提高性能(如果有的话)。也许您应该尝试使用numpy结构化数组 假设对象具有属性a和b,并且它们是双精度浮点数,那么
import numpy as np
numberOfObjects = 6
myStructuredArray = np.zeros(
(numberOfObjects,),
[("a", "f8"), ("b", "f8")],
)
可以像这样初始化对象0的各个属性
myStructuredArray["a"][0] = 1.0
myStructuredArray["a"] = [1,2,3,4,5,6]
print(myStructuredArray)
或者,您可以像这样初始化所有对象的单个属性
myStructuredArray["a"][0] = 1.0
myStructuredArray["a"] = [1,2,3,4,5,6]
print(myStructuredArray)
我不能评论,很抱歉误用了答案部分 如果numpy数组的数据类型是python对象,则numpy数组的内存不连续。操作的矢量化可能不会大大提高性能(如果有的话)。也许您应该尝试使用numpy结构化数组 假设对象具有属性a和b,并且它们是双精度浮点数,那么
import numpy as np
numberOfObjects = 6
myStructuredArray = np.zeros(
(numberOfObjects,),
[("a", "f8"), ("b", "f8")],
)
可以像这样初始化对象0的各个属性
myStructuredArray["a"][0] = 1.0
myStructuredArray["a"] = [1,2,3,4,5,6]
print(myStructuredArray)
或者,您可以像这样初始化所有对象的单个属性
myStructuredArray["a"][0] = 1.0
myStructuredArray["a"] = [1,2,3,4,5,6]
print(myStructuredArray)
numpy.ufunc
当给定一个对象数据类型数组时,遍历该数组,并尝试对每个元素应用一个CooResponse方法
例如,np.abs
尝试应用方法。让我们向类中添加这样的方法:
In [31]: class ExampleObject():
...:
...: def __init__(self, r):
...: self.r = r
...: def __abs__(self):
...: return self.r
...:
现在创建阵列:
In [32]: indexArray = 5 #arbitrary choice of array index
...: sizeArray = 10
...:
...: exampleList = []
...: for i in range(sizeArray):
...: r = np.random.rand()
...: exampleList.append( ExampleObject( r ) )
...:
...: index_list = np.arange(0,sizeArray,1)
...: index_list = np.delete(index_list,indexArray)
...:
...: coords = np.array([h.r for h in exampleList])
并从列表中创建一个对象数据类型数组:
In [33]: exampleArr = np.array(exampleList)
In [34]: exampleArr
Out[34]:
array([<__main__.ExampleObject object at 0x7fbb541eb9b0>,
<__main__.ExampleObject object at 0x7fbb541eba90>,
<__main__.ExampleObject object at 0x7fbb541eb3c8>,
<__main__.ExampleObject object at 0x7fbb541eb978>,
<__main__.ExampleObject object at 0x7fbb541eb208>,
<__main__.ExampleObject object at 0x7fbb541eb128>,
<__main__.ExampleObject object at 0x7fbb541eb198>,
<__main__.ExampleObject object at 0x7fbb541eb358>,
<__main__.ExampleObject object at 0x7fbb541eb4e0>,
<__main__.ExampleObject object at 0x7fbb541eb048>], dtype=object)
它还适用于数组的索引元素:
In [36]: np.abs(exampleArr[:3])
Out[36]:
array([0.28411876298913485, 0.5807617042932764, 0.30566195995294954],
dtype=object)
这很方便,但我不能保证速度。在其他测试中,我发现对对象数据类型的迭代比对数值数组元素的迭代(在Python中)快,但比列表迭代慢
In [37]: timeit np.abs(exampleArr)
3.61 µs ± 131 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [38]: timeit [h.r for h in exampleList]
985 ns ± 31.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [39]: timeit np.array([h.r for h in exampleList])
3.55 µs ± 88.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
numpy.ufunc
当给定一个对象数据类型数组时,遍历该数组,并尝试对每个元素应用一个CooResponse方法
例如,np.abs
尝试应用方法。让我们向类中添加这样的方法:
In [31]: class ExampleObject():
...:
...: def __init__(self, r):
...: self.r = r
...: def __abs__(self):
...: return self.r
...:
现在创建阵列:
In [32]: indexArray = 5 #arbitrary choice of array index
...: sizeArray = 10
...:
...: exampleList = []
...: for i in range(sizeArray):
...: r = np.random.rand()
...: exampleList.append( ExampleObject( r ) )
...:
...: index_list = np.arange(0,sizeArray,1)
...: index_list = np.delete(index_list,indexArray)
...:
...: coords = np.array([h.r for h in exampleList])
并从列表中创建一个对象数据类型数组:
In [33]: exampleArr = np.array(exampleList)
In [34]: exampleArr
Out[34]:
array([<__main__.ExampleObject object at 0x7fbb541eb9b0>,
<__main__.ExampleObject object at 0x7fbb541eba90>,
<__main__.ExampleObject object at 0x7fbb541eb3c8>,
<__main__.ExampleObject object at 0x7fbb541eb978>,
<__main__.ExampleObject object at 0x7fbb541eb208>,
<__main__.ExampleObject object at 0x7fbb541eb128>,
<__main__.ExampleObject object at 0x7fbb541eb198>,
<__main__.ExampleObject object at 0x7fbb541eb358>,
<__main__.ExampleObject object at 0x7fbb541eb4e0>,
<__main__.ExampleObject object at 0x7fbb541eb048>], dtype=object)
它还适用于数组的索引元素:
In [36]: np.abs(exampleArr[:3])
Out[36]:
array([0.28411876298913485, 0.5807617042932764, 0.30566195995294954],
dtype=object)
这很方便,但我不能保证速度。在其他测试中,我发现对对象数据类型的迭代比对数值数组元素的迭代(在Python中)快,但比列表迭代慢
In [37]: timeit np.abs(exampleArr)
3.61 µs ± 131 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [38]: timeit [h.r for h in exampleList]
985 ns ± 31.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In [39]: timeit np.array([h.r for h in exampleList])
3.55 µs ± 88.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
我还没有理解您的代码,但请记住,快速numpy数学只适用于数字类型。对象数据类型只包含指向内存中其他位置对象的指针。这种数组的数学运算必须迭代,就像对相同对象的列表进行迭代一样。可以使用列表为对象数据类型数组编制索引。但是您不能一次从所有这些对象中提取r
属性。您必须使用类似于coords
的构造来实现这一点。我还没有消化您的代码,但请记住,快速numpy数学只适用于数字类型。对象数据类型只包含指向内存中其他位置对象的指针。这种数组的数学运算必须迭代,就像对相同对象的列表进行迭代一样。可以使用列表为对象数据类型数组编制索引。但是您不能一次从所有这些对象中提取r
属性。您必须使用类似于coords
的构造来实现这一点。通过创建这样一个结构化数组来扩展您的注释。我已经做到了,但我想让你获得荣誉。通过创建这样一个结构化数组来扩展你的评论。我已经做到了,但我想让你得到荣誉。使用这种技术,你已经将对象列表转换为一个numpy对象数组。我有什么理由保留我的物品清单吗?出于天真无知,我列出了一张物品清单。。。如果每次我真的使用它时,我都需要将它转换为一个数组,那么我是否应该从一个numpy数组开始,并在转换每个循环时节省一些时间?在真实的程序中,这个循环超过1000万次:)这没有一个通用的答案。这取决于您打算如何构造对象数组。列表附加比数组连接更快,并且与通过预分配数组的迭代相竞争。使用此技术,您已将对象列表转换为对象的numpy数组。我有什么理由保留我的物品清单吗?出于天真无知,我列出了一张物品清单。。。如果每次我真的使用它时,我都需要将它转换为一个数组,那么我是否应该从一个numpy数组开始,并在转换每个循环时节省一些时间?在实际的程序中,这个循环超过1000万t