2

我正在玩 astropy.table 模块中的 Tables 对象。

下面的一段代码显示了我正在处理的数据类型:

In [44]: table             
Out[44]: 
<Table length=9>
defocus  source   Chi2  xcentroid ycentroid  FWHMx   FWHMy    Peak 
float32 float32 float32  float32   float32  float32 float32 float32
------- ------- ------- --------- --------- ------- ------- -------
   -0.3     0.0 346.648    2056.5     55.82 11.8635 11.8635 182.277
   -0.3     4.0 148.302   2056.49   1911.02 6.66554 6.66554 299.074
   -0.3     8.0 347.208   2056.51   3922.99 6.83129 6.83129 326.476
  -0.26     0.0 318.489    2056.5   55.8803  10.206  10.206 195.055
  -0.26     4.0 152.501   2056.51   1911.02  6.9012  6.9012 244.817
  -0.26     8.0 285.845   2056.49   3922.99  7.7939  7.7939 236.194
  -0.22     0.0 264.113    2056.5   55.9053 8.79704 8.79704 187.376
  -0.22     4.0 163.228    2056.5   1911.02 2.43716 2.43716 402.182
  -0.22     8.0 230.017    2056.5   3922.99 6.70312 6.70312 235.376

In [45]: type(table)       
Out[45]: astropy.table.table.Table

In [46]: cols=table.columns

In [47]: type(cols)
Out[47]: astropy.table.table.TableColumns

In [48]: type(cols[0])
Out[48]: astropy.table.column.Column 

In [50]: mylist_1 = [x for x in cols]

In [51]: mylist_2 = [cols[k] for k in range(len(cols))]

In [52]: type(mylist_1[0])
Out[52]: str

In [53]: type(mylist_2[0])
Out[53]: astropy.table.column.Column

In [54]: mylist_1[0]
Out[54]: 'defocus'

In [55]: mylist_2[0]
Out[55]: 
<Column name='defocus' dtype='float32' length=9>
 -0.3
 -0.3
 -0.3
-0.26
-0.26
-0.26
-0.22
-0.22
-0.22

我期待这两行:

mylist_1 = [x for x in cols]

mylist_2 = [cols[k] for k in range(len(cols))]

将完全相同(第二个不太优雅),但它没有,正如您在上面的输出中看到的那样(mylist_1 仅包含列名称,而不包含列本身)。为什么呢?关于我的“cols”对象,我有什么不明白的地方吗?

感谢您的见解。

(我在尝试将我的表写入 fit 文件时遇到了这个问题 - 使用 astropy.io.fits - 这需要构建一个适当的列列表,这并不像人们期望的那样明显......)

4

3 回答 3

2

astropy.table.table.TableColumns对象(通过属性访问columns)是有序的 dict,而不是列表。这就是为什么[x for x in cols]给出列名列表的原因(与迭代普通 dict 给出键而不是值相同)。

为方便起见,它还支持索引访问和切片,如col[0]or cols[1:3]。但即使它支持类似列表的访问,TableColumns首先也是最重要的一个字典。

PR #4394中将添加一个新itercols()方法,该方法将支持cols_list = [x for x in t.itercols()].

于 2016-04-21T12:57:04.573 回答
0

astropy.table.table.TableColumns 是 astropy 包的一个定义项。它是 TableColumns 类的一个实例,基本上你不应该使用迭代器“cols[k]”或“in cols”来访问它。

但是在一个类中你可以定义方法contains () 和getitem () 来描述这两个请求的行为。见https://infohost.nmt.edu/tcc/help/pubs/python/web/special-methods.html

在这里,定义的行为似乎与经典的元素列表不同。也许一些文档可用于 astropy 课程。

于 2016-04-21T10:12:06.827 回答
0

您的循环在列上迭代略有不同(但等效)。但是您在列表理解中附加了不同的内容。这些列是dict-like 所以它们有一个索引和一个关联的元素:

考虑这样的表:

from astropy.table import Table

data_rows = [(1, 2.0, 'x'),
             (4, 5.0, 'y'),
             (5, 8.2, 'z')]
t = Table(rows=data_rows, names=('a', 'b', 'c'), meta={'name': 'first table'},
          dtype=('i4', 'f8', 'S1'))
cols=t.columns

您可以使用以下方法迭代列索引

[x for x in cols]
# ['a', 'b', 'c']

或者

[k for k in range(len(cols))]
# [0, 1, 2]

这些看起来不同,但cols[0] == cols['a']这些只是索引列的两种不同方法。

但是,如果您想迭代实际列而不是它们的索引,您可以这样做:

[cols[x] for x in cols]
# [<Column name='a' dtype='int32' length=3>1   4   5, 
# <Column name='b' dtype='float64' length=3>2.0  5.0   8.2,
# <Column name='c' dtype='bytes1' length=3> x   y    z]

或者:

[cols[k] for k in range(len(cols))]
# [<Column name='a' dtype='int32' length=3>1   4   5, 
# <Column name='b' dtype='float64' length=3>2.0  5.0   8.2,
# <Column name='c' dtype='bytes1' length=3> x   y    z]

这次我们实际上是插入索引列而不是插入索引。

然而,这并不意味着您将转换为 FITS,但您始终可以将您的表格直接保存为他们的任何格式,查看他们支持的格式

例如,写一个 fit 就像使用一样简单:

t.write('new_table.fits')

或者

t.write('new_table.fits', format='fits')
于 2016-04-21T10:33:56.920 回答