Astropy ICRS 到 Galactocentric 转换 Numpy AttributeError
Astropy ICRS to Galactocentric transformation Numpy AttributeError
我需要将一个大型 ICRS 数据库(大约 10 亿条数据)转换为银河系坐标。首先,我尝试使用将我的数据转换为 coord.ICRS,然后在迭代循环中将这些数据转换为 coord.Galactocentric。但这是非常耗时的。四处搜索,我 在 coord.Skycoord 中,您可以使用数据数组进行转换。所以我在我的代码中实现了解决方案:
data = pd.read_csv('/content/data (1).csv')
data_ra = data['ra']
data_dec = data['dec']
data_dist = data['r_est']
data_ra = data_ra * u.degree
data_dec = data_dec * u.degree
data_dist = data_dist * u.pc
c = coord.ICRS(data_ra, data_dec, data_dist)
c = c.transform_to(coord.Galactocentric)
x = c.x.value
y = c.y.value
z = c.z.value
它returns错误代码:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-26-e02bbc9ec5dd> in <module>()
6 data_dec = data_dec * u.degree
7 data_dist = data_dist * u.pc
----> 8 c = coord.ICRS(data_ra, data_dec, data_dist)
9 c = c.transform_to(coord.Galactocentric)
10 x = c.x.value
5 frames
/usr/local/lib/python3.6/dist-packages/astropy/units/quantity.py in __new__(cls, value, unit, dtype, copy, order, subok, ndmin)
340 # Convert all quantities to the same unit.
341 if unit is None:
--> 342 unit = value[0].unit
343 value = [q.to_value(unit) for q in value]
344 value_unit = unit # signal below that conversion has been done
AttributeError: 'numpy.float64' object has no attribute 'unit'
我似乎无法解决问题,coord.ICRS 数组不兼容吗?如果是这样,我怎样才能加快转型的进程。
这也让我有点吃惊。但是,原因是当您访问 Pandas DataFrame
的列时,它不是 return 普通的 Numpy 数组,而是 Pandas Series
对象(我用一些虚拟数据测试了这个):
>>> data_ra = data['ra']
>>> type(data_ra)
<class 'pandas.core.series.Series'>
似乎(我觉得这有点问题),虽然你可以将 Series
乘以一个单位,但它不能正常工作:
>>> data_ra = data_ra * u.degree
>>> type(data_ra)
<class 'pandas.core.series.Series'>
因此,它并没有像您希望的那样得到一个 Astropy Quantity
,而是返回一个 Series
。事实上,Quantity
仍然在那里,在 Series
' .value
属性中:
>>> data_ra.values
<Quantity [ 1., 2., 3.] deg>
但是在这种情况下其他的东西都坏了。首先创建 Quantity
s 更好的方法是在每个 Series
上使用 .values
属性——这个 returns 是一个可以转换的普通 Numpy 数组Quantity
:
>>> data_ra = df['ra'].values * u.degree
>>> data_dec = data['dec'].values * u.degree
>>> data_dist = data['dist'].values * u.pc
>>> c = coord.ICRS(data_ra, data_dec, data_dist)
>>> c
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, pc)
[( 1., 4., 7.), ( 2., 5., 8.), ( 3., 6., 9.)]>
>>> c.transform_to(coord.Galactocentric)
<Galactocentric Coordinate (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
( 266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=( 11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg): (x, y, z) in pc
[(-8300.70096432, 3.76036129, 21.14296691),
(-8300.99504334, 4.33255373, 20.35548782),
(-8301.33502602, 4.91092559, 19.5850604 )]>
更好的是,除非你需要使用 Pandas 做其他事情,你还可以使用 Astropy 读取 CSV 文件和 return Table
of Quantity
s在所需的尺寸。例如,
>>> t = Table.read('foo.csv')
>>> for col, unit in [('ra', u.degree), ('dec', u.degree), ('dist', u.pc)]:
... t[col].unit = unit
...
>>> t
<Table length=3>
col0 dec dist ra
deg pc deg
int64 float64 float64 float64
----- ------- ------- -------
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0
>>> coord.ICRS(t['ra'], t['dec'], t['dist'])
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, pc)
[( 1., 4., 7.), ( 2., 5., 8.), ( 3., 6., 9.)]>
有点不幸的是,没有办法(我能找到)直接在 Table.read()
调用中指定列维度。这可能是对 API.
的一个很好的补充
但是,如果您将 Table
写回到 ECSV 文件,它将以类似于 CSV 的格式保存它,但包含用于重建 table 阅读后,包括设置单位:
>>> t.write('foo.ecsv')
>>> Table.read('foo.ecsv')
<Table length=3>
col0 dec dist ra
deg pc deg
int64 float64 float64 float64
----- ------- ------- -------
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0
>>> print(open('foo.ecsv').read())
# %ECSV 0.9
# ---
# datatype:
# - {name: col0, datatype: int64}
# - {name: dec, unit: deg, datatype: float64}
# - {name: dist, unit: pc, datatype: float64}
# - {name: ra, unit: deg, datatype: float64}
# schema: astropy-2.0
col0 dec dist ra
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0
我需要将一个大型 ICRS 数据库(大约 10 亿条数据)转换为银河系坐标。首先,我尝试使用将我的数据转换为 coord.ICRS,然后在迭代循环中将这些数据转换为 coord.Galactocentric。但这是非常耗时的。四处搜索,我
data = pd.read_csv('/content/data (1).csv')
data_ra = data['ra']
data_dec = data['dec']
data_dist = data['r_est']
data_ra = data_ra * u.degree
data_dec = data_dec * u.degree
data_dist = data_dist * u.pc
c = coord.ICRS(data_ra, data_dec, data_dist)
c = c.transform_to(coord.Galactocentric)
x = c.x.value
y = c.y.value
z = c.z.value
它returns错误代码:
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-26-e02bbc9ec5dd> in <module>()
6 data_dec = data_dec * u.degree
7 data_dist = data_dist * u.pc
----> 8 c = coord.ICRS(data_ra, data_dec, data_dist)
9 c = c.transform_to(coord.Galactocentric)
10 x = c.x.value
5 frames
/usr/local/lib/python3.6/dist-packages/astropy/units/quantity.py in __new__(cls, value, unit, dtype, copy, order, subok, ndmin)
340 # Convert all quantities to the same unit.
341 if unit is None:
--> 342 unit = value[0].unit
343 value = [q.to_value(unit) for q in value]
344 value_unit = unit # signal below that conversion has been done
AttributeError: 'numpy.float64' object has no attribute 'unit'
我似乎无法解决问题,coord.ICRS 数组不兼容吗?如果是这样,我怎样才能加快转型的进程。
这也让我有点吃惊。但是,原因是当您访问 Pandas DataFrame
的列时,它不是 return 普通的 Numpy 数组,而是 Pandas Series
对象(我用一些虚拟数据测试了这个):
>>> data_ra = data['ra']
>>> type(data_ra)
<class 'pandas.core.series.Series'>
似乎(我觉得这有点问题),虽然你可以将 Series
乘以一个单位,但它不能正常工作:
>>> data_ra = data_ra * u.degree
>>> type(data_ra)
<class 'pandas.core.series.Series'>
因此,它并没有像您希望的那样得到一个 Astropy Quantity
,而是返回一个 Series
。事实上,Quantity
仍然在那里,在 Series
' .value
属性中:
>>> data_ra.values
<Quantity [ 1., 2., 3.] deg>
但是在这种情况下其他的东西都坏了。首先创建 Quantity
s 更好的方法是在每个 Series
上使用 .values
属性——这个 returns 是一个可以转换的普通 Numpy 数组Quantity
:
>>> data_ra = df['ra'].values * u.degree
>>> data_dec = data['dec'].values * u.degree
>>> data_dist = data['dist'].values * u.pc
>>> c = coord.ICRS(data_ra, data_dec, data_dist)
>>> c
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, pc)
[( 1., 4., 7.), ( 2., 5., 8.), ( 3., 6., 9.)]>
>>> c.transform_to(coord.Galactocentric)
<Galactocentric Coordinate (galcen_coord=<ICRS Coordinate: (ra, dec) in deg
( 266.4051, -28.936175)>, galcen_distance=8.3 kpc, galcen_v_sun=( 11.1, 232.24, 7.25) km / s, z_sun=27.0 pc, roll=0.0 deg): (x, y, z) in pc
[(-8300.70096432, 3.76036129, 21.14296691),
(-8300.99504334, 4.33255373, 20.35548782),
(-8301.33502602, 4.91092559, 19.5850604 )]>
更好的是,除非你需要使用 Pandas 做其他事情,你还可以使用 Astropy 读取 CSV 文件和 return Table
of Quantity
s在所需的尺寸。例如,
>>> t = Table.read('foo.csv')
>>> for col, unit in [('ra', u.degree), ('dec', u.degree), ('dist', u.pc)]:
... t[col].unit = unit
...
>>> t
<Table length=3>
col0 dec dist ra
deg pc deg
int64 float64 float64 float64
----- ------- ------- -------
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0
>>> coord.ICRS(t['ra'], t['dec'], t['dist'])
<ICRS Coordinate: (ra, dec, distance) in (deg, deg, pc)
[( 1., 4., 7.), ( 2., 5., 8.), ( 3., 6., 9.)]>
有点不幸的是,没有办法(我能找到)直接在 Table.read()
调用中指定列维度。这可能是对 API.
但是,如果您将 Table
写回到 ECSV 文件,它将以类似于 CSV 的格式保存它,但包含用于重建 table 阅读后,包括设置单位:
>>> t.write('foo.ecsv')
>>> Table.read('foo.ecsv')
<Table length=3>
col0 dec dist ra
deg pc deg
int64 float64 float64 float64
----- ------- ------- -------
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0
>>> print(open('foo.ecsv').read())
# %ECSV 0.9
# ---
# datatype:
# - {name: col0, datatype: int64}
# - {name: dec, unit: deg, datatype: float64}
# - {name: dist, unit: pc, datatype: float64}
# - {name: ra, unit: deg, datatype: float64}
# schema: astropy-2.0
col0 dec dist ra
0 4.0 7.0 1.0
1 5.0 8.0 2.0
2 6.0 9.0 3.0