用对象实例填充 NumPy 数组?

Filling NumPy array with object instances?

我正在尝试将 astropy Angles 的对象实例添加到 NumPy 数组,但出现错误:

ValueError: setting an array element with a sequence.

Angle 对象看起来像这样:

<Angle 1.2557346257567 deg>

如果我将它们放在一个正常的 Python 列表中,那么我会得到:

s = [<Angle 1.2562500714928306 deg>,
     <Angle 1.2562500714928306 deg>,
     <Angle 1.2562500714928306 deg>]
len(s)
>>> 3
len(s[0])
>>> TypeError: 'Angle' object with a scalar value has no len()

所以,我的第一个问题是,Python 对象在什么方面是一个序列?而且,由于需要将 numpy 数组初始化为特定维度,我如何找到此对象的 "length" 以便我可以将它们加载到 numpy 数组中?

我没有 astrop 包,也不知道 Angle 对象的详细信息。但我可以做一些 Python 和 numpy 观察。

<Angle 1.2557346257567 deg> 是此对象的字符串表示形式,由其 __repr__ 方法生成。

len(s[0]) 的 TypeError 意味着该对象没有 __len__ 方法。它不是列表的子类,也不是专门的 numpy 数组。检查它的文档。它可能有产生一个或多个数值的方法。

你没有说你是如何尝试 'add' 一个数组的角度,或者什么样的数组。如果数组是数字,例如dtype=float,然后做

A[0]= <Angle...> 

是行不通的,因为 Angle 不是数字,也不会产生数字——至少在没有某种方法的情况下不会。您需要告诉我们这个目标数组应该包含什么。数字、角度物体?

您可以构建一个包含对象的数组。 np.array(s) 可能有效。它在列表包含字典对象时执行。

In [67]: ll
Out[67]: [{1: 2}, {}, {'a': 1, 'b': 2}]

In [68]: np.array(ll)
Out[68]: array([{1: 2}, {}, {'b': 2, 'a': 1}], dtype=object)

但是 np.array([...]) 使用起来可能很棘手,因为它旨在生成多维数字数组 - 如果可能的话。

或者您可能需要创建 A = np.zeros((3,),dtype=object) 数组,并单独赋值,A[0]=s[0]。但是这样的对象数组只是列表的一个变体。它不是二维数组。

来自之前的 astropy 个问题:

Angle(angles_quantity).wrap_at('360d').value # This returns a simple ndarray again.

=================

深入研究文档和 astropy github 代码,我看到 AngleQuantity 的子类,Quantityndarray 的子类。它实际上是一个具有适当 unit 定义的数组(或标量)。

.value方法returnsself.view(np.ndarray),除非它的形状是0d,在这种情况下它returnsself.item(),标量值。

因此您应该能够定义具有多个值的 Angle,例如

Angle([1.23, 1.24, 1.25])

不知道能不能把多个Angles拼成一个

Angle(s)

其中 s 是您的 Angle 对象列表,可能会起作用。我没有看到 concatenatestack.

Angle 版本

您可以将数组的 dtype 设置为 object,一个简单的例子是

import numpy as np
from astropy.coordinates import Angle
a, b, c = Angle('1.2562500714928306d'), Angle('1.2562500714928306d'), Angle('1.2562500714928306d')
s = np.array([a, b, c], dtype=object)

不要创建 Angle 个对象的列表或数组。
相反,将 Angle(和类似的 astropy 类)视为添加单元的容器对象,并使用列表或数组对其进行初始化。

例如:

>>> from astropy.coordinates import Angle
>>> from astropy import units
>>> angles = Angle([0, 30, 60, 90], unit=units.degree)
>>> angles
<Angle [  0., 30., 60., 90.] deg>

>>> angles = Angle(np.linspace(0, 90, 15, endpoint=True), unit=units.degree)
>>> angles
<Angle [  0.        ,  6.42857143, 12.85714286, 19.28571429, 25.71428571,
         32.14285714, 38.57142857, 45.        , 51.42857143, 57.85714286,
         64.28571429, 70.71428571, 77.14285714, 83.57142857, 90.        ] deg>
>>> len(angles)
15

这是一种更有效的使用 astropy 类 的方法:您现在可以简单地将 angles 乘以一个值,或对其执行其他操作,就像对 numpy 数组一样。