我有一个对象数组。我还有一个函数,一次需要两个对象的信息。我想对函数的调用进行矢量化处理,以便它一次计算所有调用,而不是使用循环来遍历必要的对象对。
如果我改用必要的数据创建一个数组,我就可以使用它。但是,这部分地破坏了使用对象的目的。
这是代码。它当前使用数组方法工作,并且在功能中只需注释/取消注释即可切换到不起作用的“对象”模式,但我非常希望这样做。
我得到的错误是:TypeError:只有具有一个元素的整数数组才能转换为索引
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)
问题在于,当我向函数传递一个整数数组时,当我使用对象数组(实际上是列表)时,它不返回答案数组(我想要的矢量化)。如果我使用数组(没有对象,每个元素中只有数据),它确实可以工作。但是正如我已经说过的那样,这在我的脑海中是无法实现的,它的目的是要在对象上存储信息。我真的还需要在数组中存储相同的信息吗?
答案 0 :(得分:3)
我无法发表评论,对您滥用答案部分表示抱歉...
如果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)
[(1., 0.) (2., 0.) (3., 0.) (4., 0.) (5., 0.) (6., 0.)]
答案 1 :(得分:2)
numpy.ufunc
,在给定对象dtype数组时,对其进行迭代,然后尝试对每个元素应用对应的方法。
例如np.abs
尝试应用__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])
并从列表中创建对象dtype数组:
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)
现在,我们可以通过调用r
函数来获取np.abs
值的数组:
In [35]: np.abs(exampleArr)
Out[35]:
array([0.28411876298913485, 0.5807617042932764, 0.30566195995294954,
0.39564156171554554, 0.28951905026871105, 0.5500945908978057,
0.40908712567465855, 0.6469497088949425, 0.7480045751535003,
0.710425181488751], dtype=object)
它也适用于数组的索引元素:
In [36]: np.abs(exampleArr[:3])
Out[36]:
array([0.28411876298913485, 0.5807617042932764, 0.30566195995294954],
dtype=object)
这很方便,但是我不能保证速度。在其他测试中,我发现对象dtype的迭代比数字数组元素的迭代快(在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)