Python Numpy值错误:使用序列设置数组元素

Python Numpy值错误:使用序列设置数组元素,python,arrays,numpy,astropy,Python,Arrays,Numpy,Astropy,我正在使用numpy和astropy用Python编写代码。在代码中,我希望创建通常类似于我的数据集的随机numpy数组。之后,我想把这些球坐标的随机数组转换成笛卡尔坐标。不幸的是,我一直得到一个值错误,我完全不明白为什么会发生这种情况。我尝试过做一些虚拟测试,例如,如果它们是相同的形状,所有数组都有合理的值和相同的类型,等等。但我被卡住了。这是我的密码: from astropy.coordinates import SkyCoord from astropy import units as

我正在使用numpy和astropy用Python编写代码。在代码中,我希望创建通常类似于我的数据集的随机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.
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\pythols\visualstudio\u py\u launcher.py''C:\Users\sirep\Documents\C++scripts''57764''34806ad9-833a-4524-8cd6-18ca4aa74f14''重定向输出,重定向输出''C:\Users\sirep文档\python scripts\python脚本\sph2cart.py
(262615,)
(262615,)
(262615,)
(262615,)
回溯(最近一次呼叫最后一次):
文件“c:\Users\sirep\Documents\Python Scripts\sph2cart.py”,第16行,在
c[i]=SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc)
ValueError:使用序列设置数组元素。

谢谢大家抽出时间

我已经找出了我的错误。SkyCoord返回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])

我想我应该把我的答案扩展到一个更长的答案,因为这里有一些东西值得未来读者解释和澄清

你在信中写道:


我已经发现了我的错误。SkyCoord返回3个值:x坐标、y坐标和z坐标。我试图给数组的单个元素分配三个值

这当然是正确的,但并不完全正确。在原始代码中,您有如下内容:

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
虽然您不能将
SkyCoord
直接分配到这些值中的一个(我认为从技术上讲,
SkyCoord
被视为无坐标,无论您使用什么坐标系来实例化它,但我可能错了),但您可以分配例如:

>>> c[0] = SkyCoord(ra=ra[i]*u.degree,dec=dec[i]*u.degree,distance=R[i]*u.mpc).cartesian.xyz
但是,这仍然没有必要,因为正如我在评论中提到并进一步解释的那样,
SkyCoord
可以表示一个坐标数组,如:

>>> coords = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
>>> x, y, z = coords.cartesian.xyz
您可以一次将所有这些转换为笛卡尔坐标,并检索x、y和z坐标的单独数组,如:

>>> coords = SkyCoord(ra=ra*u.degree, dec=dec*u.degree, distance=R*u.mpc)
>>> x, y, z = coords.cartesian.xyz
这还有一个额外的优点,即使用最合适的长度维度(在本例中为Mpc,因为这是您在中给出的距离)将坐标返回为
Quantity
s。但是,
coords.cartesian
本身实际上已经是一个
(x,y,z)
坐标数组,非常类似于上面的结构化数组示例(从技术上讲,它不是Numpy数组,但它有许多相同的方法,可以转换为类似的方法):

或111ms表示原始示例中的
262615
坐标。然而,以“天真”的方式做这件事让我:

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

错误告诉您,您正在尝试使用数组或序列设置单个元素,
SkyCoord
在此返回什么?这是一个元组吗?我想我知道这段代码哪里出了问题,SkyCoord返回了3个值x,y,z,我将它赋给数组中的一个元素。您将
c
声明为一个浮点数组,但您尝试用
SkyCoord
对象赋给
c[I]
。或者,您可以使用空列表声明
c
,并使用
c.append
填充
SkyCoord
实例。您正在执行的Python循环非常缓慢
SkyCoord
直接作用于坐标数组:
coords=SkyCoord(ra=ra*u.degree,dec=dec*u.degree,distance=R*u.mpc)
。这基本上是天空坐标的向量
coords.cartesian
将给出坐标的笛卡尔表示数组(作为
(x,y,z)
元组的数组)。如果希望每个坐标作为单独的数组,可以执行
x,y,z=coords.cartesian.get_xyz()
。您将看到,这将返回
数量
,这也保留了维度。谢谢,我对python比较陌生,因此时间安排对我来说是一个关键性的区别,它肯定会将代码优化到更高的程度。
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