Numpy Value Error: setting an array element with a sequence
Numpy Value Error: setting an array element with a sequence
我正在 Python 使用 numpy 和 astropy 编写代码。在代码中,我希望创建通常类似于我的数据集的随机 numpy 数组。之后我想将这些随机的球坐标数组转换为笛卡尔坐标。不幸的是,我一直收到一个值错误,我完全不知道为什么会这样 我尝试做一些虚拟测试,例如它们是否具有相同的形状,所有数组的值是否合理且类型相同,等等。但是我卡住了。这是我的代码:
from astropy.coordinates import SkyCoord
from astropy import units as u
import numpy as np
R = 445 + np.random.randn(262615)
print(np.shape(R))
dec = 2 + np.random.randn(262615)
print(np.shape(dec))
ra = 150 + np.random.randn(262615)
print(np.shape(ra))
c = np.zeros(262615)
print(np.shape(c))
for i in range(262615):
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
print(c[i])
这是我的错误信息:
PS C:\Users\sirep\Documents\C++ scripts> cd 'c:\Users\sirep\Documents\C++ scripts'; ${env:PYTHONIOENCODING}='UTF-8'; ${env:PYTHONUNBUFFERED}='1'; & 'C:\Users\sirep\Anaconda3\python.exe' 'c:\Users\sirep\.vscode\extensions\ms-python.python-2018.5.0\pythonFiles\PythonTools\visualstudio_py_launcher.py' 'c:\Users\sirep\Documents\C++ scripts' '57764' '34806ad9-833a-4524-8cd6-18ca4aa74f14' 'RedirectOutput,RedirectOutput' 'c:\Users\sirep\Documents\Python Scripts\sph2cart.py'
(262615,)
(262615,)
(262615,)
(262615,)
Traceback (most recent call last):
File "c:\Users\sirep\Documents\Python Scripts\sph2cart.py", line 16, in <module>
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
ValueError: setting an array element with a sequence.
谢谢大家的宝贵时间!
我发现了我的错误。 SkyCoord returns 3 值 x 坐标、y 坐标和 z 坐标。我试图将三个值分配给数组的单个元素。为了解决这个问题,我必须首先为每个坐标创建 3 个单独的数组,然后确保每个值在输入到各自的数组时都是无量纲的:
from astropy.coordinates import SkyCoord
from astropy import units as u
import numpy as np
R = 445 + np.random.randn(262615)
print(np.shape(R))
dec = 2 + np.random.randn(262615)
print(np.shape(dec))
ra = 150 + np.random.randn(262615)
print(np.shape(ra))
cx = np.zeros(262615)
cy = np.zeros(262615)
cz = np.zeros(262615)
print(np.shape(cx))
for i in range(262):
c = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
cx[i] = c.cartesian.x.value
cy[i] = c.cartesian.y.value
cz[i] = c.cartesian.z.value
print(cx[i],cy[i],cz[i])
我认为我应该将我的 扩展为更长的答案,因为这里的一些事情值得为未来的读者解释和澄清。
在 你写道:
I've figured out my error. SkyCoord returns 3 values an x coordinate, y coordinate and z coordinate. I was trying to assign three values to a single element of an array.
这肯定是在正确的轨道上,但不完全正确。在您的原始代码中,您有类似的内容:
c = np.zeros(262615)
这已经有点自找麻烦了,因为您没有指定数据类型,但默认情况下数据类型是 float64
,这可能是您想要的许多应用程序的类型(对于这个应用程序当然是正确的) .在任何情况下,正在键入的 Numpy 数组意味着如果您像在原始代码中那样分配给数组的单个元素:
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
您分配的值最好是浮点数,或者至少是可以明确转换为浮点数的其他数字类型(如 int
)。 SkyCoord
并非如此,因为正如您所指出的,它是三个维度的多重态。我的观点是,一般来说,如果您使用 Numpy 数组,您需要注意它的 dtype
是什么以及您试图分配给它的元素的内容。对于更多任意对象,您更有可能得到更清晰的错误,例如:
>>> c[0] = object()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: float() argument must be a string or a number
仍然不是很好,但至少它表明它正在尝试调用 float()
将参数转换为浮点数。但是 SkyCoord
会得到不同的结果,因为 SkyCoord
可以是许多坐标数组的容器,Numpy 看到了这一点,而是试图像将一系列值分配给标量,这是你得到的错误。
顺便说一下,在 Numpy 中也可以使用 structured arrays 创建更复杂的数组类型。这允许您创建一个 (x, y, z)
坐标数组,例如:
>>> c = np.zeros(262615, dtype=[('x', 'f8'), ('y', 'f8'), ('z', 'f8')])
>>> c
array([(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0), ...,
(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0)],
dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
>>> c[0]
(0.0, 0.0, 0.0)
尽管您不能将 SkyCoord
直接分配给这些值之一(我认为从技术上讲 SkyCoord
被视为无坐标,无论您使用什么坐标系来实例化它,但我可能错了),你可以分配例如:
>>> c[0] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc).cartesian.xyz
但是,这仍然不是必需的,因为正如我在评论中提到并进一步解释的那样 in the docs SkyCoord
可以表示坐标数组,例如:
>>> coords = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
并且您可以一次性将其全部转换为笛卡尔坐标,并为 x、y 和 z 坐标检索单独的数组,例如:
>>> x, y, z = coords.cartesian.xyz
这有一个额外的好处,即使用最合适的长度维度(在本例中为 Mpc,因为这是您给出的距离),坐标作为 Quantity
s 返回。但是,coords.cartesian
本身实际上已经是一个 (x, y, z)
坐标数组,很像我上面的结构化数组示例(从技术上讲,它不是 Numpy 数组,但它有许多相同的方法,可以转换为一个喜欢):
>>> coords.cartesian._values
array([(0.19718680211339326, 0.002173755110841713, 0.0021735811221131776),
(0.6853033697941637, 0.005924402286034272, 0.004262079913938389),
...
dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
但这是一个未记录的内部属性,不应使用(尽管我不确定为什么不公开此接口,因为它可能很有用...)
最后,我要补充一点,使用这个接口要快得多,因为所有循环都是向量化数组操作,主要是在 C 中。任何时候你在 Python 级别做事情,比如分配给数组 (c[i] = ...
) 或属性访问 (c.cartesian.x.value
) 您会招致严重的性能损失,因为值需要从 C 转换为 Python 并再次转换回 C。使用矢量化操作可以避免这一切。所以当我制作一个 SkyCoord
数组时,我得到:
In [7]: %%timeit
...: c = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
...: c.cartesian.xyz
...:
10 loops, best of 3: 111 ms per loop
或 262615
坐标为 111 毫秒,如您的原始示例所示。而 "naïve" 的方式让我得到:
In [11]: %%timeit
...: for i in range(262615):
...: c = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
...: cx[i] = c.cartesian.x.value
...: cy[i] = c.cartesian.y.value
...: cz[i] = c.cartesian.z.value
...:
1 loop, best of 3: 18min 26s per loop
我正在 Python 使用 numpy 和 astropy 编写代码。在代码中,我希望创建通常类似于我的数据集的随机 numpy 数组。之后我想将这些随机的球坐标数组转换为笛卡尔坐标。不幸的是,我一直收到一个值错误,我完全不知道为什么会这样 我尝试做一些虚拟测试,例如它们是否具有相同的形状,所有数组的值是否合理且类型相同,等等。但是我卡住了。这是我的代码:
from astropy.coordinates import SkyCoord
from astropy import units as u
import numpy as np
R = 445 + np.random.randn(262615)
print(np.shape(R))
dec = 2 + np.random.randn(262615)
print(np.shape(dec))
ra = 150 + np.random.randn(262615)
print(np.shape(ra))
c = np.zeros(262615)
print(np.shape(c))
for i in range(262615):
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
print(c[i])
这是我的错误信息:
PS C:\Users\sirep\Documents\C++ scripts> cd 'c:\Users\sirep\Documents\C++ scripts'; ${env:PYTHONIOENCODING}='UTF-8'; ${env:PYTHONUNBUFFERED}='1'; & 'C:\Users\sirep\Anaconda3\python.exe' 'c:\Users\sirep\.vscode\extensions\ms-python.python-2018.5.0\pythonFiles\PythonTools\visualstudio_py_launcher.py' 'c:\Users\sirep\Documents\C++ scripts' '57764' '34806ad9-833a-4524-8cd6-18ca4aa74f14' 'RedirectOutput,RedirectOutput' 'c:\Users\sirep\Documents\Python Scripts\sph2cart.py'
(262615,)
(262615,)
(262615,)
(262615,)
Traceback (most recent call last):
File "c:\Users\sirep\Documents\Python Scripts\sph2cart.py", line 16, in <module>
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
ValueError: setting an array element with a sequence.
谢谢大家的宝贵时间!
我发现了我的错误。 SkyCoord returns 3 值 x 坐标、y 坐标和 z 坐标。我试图将三个值分配给数组的单个元素。为了解决这个问题,我必须首先为每个坐标创建 3 个单独的数组,然后确保每个值在输入到各自的数组时都是无量纲的:
from astropy.coordinates import SkyCoord
from astropy import units as u
import numpy as np
R = 445 + np.random.randn(262615)
print(np.shape(R))
dec = 2 + np.random.randn(262615)
print(np.shape(dec))
ra = 150 + np.random.randn(262615)
print(np.shape(ra))
cx = np.zeros(262615)
cy = np.zeros(262615)
cz = np.zeros(262615)
print(np.shape(cx))
for i in range(262):
c = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
cx[i] = c.cartesian.x.value
cy[i] = c.cartesian.y.value
cz[i] = c.cartesian.z.value
print(cx[i],cy[i],cz[i])
我认为我应该将我的
在
I've figured out my error. SkyCoord returns 3 values an x coordinate, y coordinate and z coordinate. I was trying to assign three values to a single element of an array.
这肯定是在正确的轨道上,但不完全正确。在您的原始代码中,您有类似的内容:
c = np.zeros(262615)
这已经有点自找麻烦了,因为您没有指定数据类型,但默认情况下数据类型是 float64
,这可能是您想要的许多应用程序的类型(对于这个应用程序当然是正确的) .在任何情况下,正在键入的 Numpy 数组意味着如果您像在原始代码中那样分配给数组的单个元素:
c[i] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
您分配的值最好是浮点数,或者至少是可以明确转换为浮点数的其他数字类型(如 int
)。 SkyCoord
并非如此,因为正如您所指出的,它是三个维度的多重态。我的观点是,一般来说,如果您使用 Numpy 数组,您需要注意它的 dtype
是什么以及您试图分配给它的元素的内容。对于更多任意对象,您更有可能得到更清晰的错误,例如:
>>> c[0] = object()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: float() argument must be a string or a number
仍然不是很好,但至少它表明它正在尝试调用 float()
将参数转换为浮点数。但是 SkyCoord
会得到不同的结果,因为 SkyCoord
可以是许多坐标数组的容器,Numpy 看到了这一点,而是试图像将一系列值分配给标量,这是你得到的错误。
顺便说一下,在 Numpy 中也可以使用 structured arrays 创建更复杂的数组类型。这允许您创建一个 (x, y, z)
坐标数组,例如:
>>> c = np.zeros(262615, dtype=[('x', 'f8'), ('y', 'f8'), ('z', 'f8')])
>>> c
array([(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0), ...,
(0.0, 0.0, 0.0), (0.0, 0.0, 0.0), (0.0, 0.0, 0.0)],
dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
>>> c[0]
(0.0, 0.0, 0.0)
尽管您不能将 SkyCoord
直接分配给这些值之一(我认为从技术上讲 SkyCoord
被视为无坐标,无论您使用什么坐标系来实例化它,但我可能错了),你可以分配例如:
>>> c[0] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc).cartesian.xyz
但是,这仍然不是必需的,因为正如我在评论中提到并进一步解释的那样 in the docs SkyCoord
可以表示坐标数组,例如:
>>> coords = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
并且您可以一次性将其全部转换为笛卡尔坐标,并为 x、y 和 z 坐标检索单独的数组,例如:
>>> x, y, z = coords.cartesian.xyz
这有一个额外的好处,即使用最合适的长度维度(在本例中为 Mpc,因为这是您给出的距离),坐标作为 Quantity
s 返回。但是,coords.cartesian
本身实际上已经是一个 (x, y, z)
坐标数组,很像我上面的结构化数组示例(从技术上讲,它不是 Numpy 数组,但它有许多相同的方法,可以转换为一个喜欢):
>>> coords.cartesian._values
array([(0.19718680211339326, 0.002173755110841713, 0.0021735811221131776),
(0.6853033697941637, 0.005924402286034272, 0.004262079913938389),
...
dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')])
但这是一个未记录的内部属性,不应使用(尽管我不确定为什么不公开此接口,因为它可能很有用...)
最后,我要补充一点,使用这个接口要快得多,因为所有循环都是向量化数组操作,主要是在 C 中。任何时候你在 Python 级别做事情,比如分配给数组 (c[i] = ...
) 或属性访问 (c.cartesian.x.value
) 您会招致严重的性能损失,因为值需要从 C 转换为 Python 并再次转换回 C。使用矢量化操作可以避免这一切。所以当我制作一个 SkyCoord
数组时,我得到:
In [7]: %%timeit
...: c = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
...: c.cartesian.xyz
...:
10 loops, best of 3: 111 ms per loop
或 262615
坐标为 111 毫秒,如您的原始示例所示。而 "naïve" 的方式让我得到:
In [11]: %%timeit
...: for i in range(262615):
...: c = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
...: cx[i] = c.cartesian.x.value
...: cy[i] = c.cartesian.y.value
...: cz[i] = c.cartesian.z.value
...:
1 loop, best of 3: 18min 26s per loop