【问题标题】:Astropy ICRS to Galactocentric transformation Numpy AttributeErrorAstropy ICRS 到 Galactocentric 转换 Numpy AttributeError
【发布时间】:2019-12-14 21:36:54
【问题描述】:

我需要将一个大型 ICRS 数据库(大约 10 亿个数据)转换为星系中心坐标。首先,我尝试使用将我的数据转换为 coord.ICRS,然后在迭代循环中将这些转换为 coord.Galactocentric。但这非常耗时。环顾四周,我 found 在 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 

返回错误码:

---------------------------------------------------------------------------

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 与数组不兼容吗?如果是这样,我怎样才能加快转型过程。

【问题讨论】:

    标签: python numpy astropy


    【解决方案1】:

    这也让我有点吃惊。但是,原因是当您访问 Pandas DataFrame 的列时,它不会返回一个普通的 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>
    

    但在这种情况下,其他事情都被破坏了。首先创建Quantitys 更好的方法是在每个Series 上使用.values 属性——这会返回一个可以转换为Quantity 的普通Numpy 数组:

    >>> 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 文件并以所需尺寸返回 Quantitys 中的 Table。例如,

    >>> 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 的格式保存,但包含用于在读取时重建表格的额外元数据,包括设置单位:

    >>> 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
    

    【讨论】:

    • 昨晚我意识到添加 .values 确实有效(不确定它是否正常工作),但使用 astropy 导入 csv 文件实际上是个好主意,谢谢 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 1970-01-01
    • 2020-10-01
    • 1970-01-01
    • 2020-12-15
    • 2022-01-14
    相关资源
    最近更新 更多