构造表#

表的初始构造方式具有很大的灵活性。输入的详细信息 TableQTable 构造函数在 Initialization Details 第节。然而,理解如何制作表格的最好方法是通过示例。

实例#

安装程序#

对于以下示例,您需要导入 QTableTableColumn 类和 单位和数量 (astropy.units ) 包装与 numpy 包裹::

>>> from astropy.table import QTable, Table, Column
>>> from astropy import units as u
>>> import numpy as np

从头开始创建#

A Table 可以在没有任何初始输入数据甚至没有任何初始列的情况下创建。如果初始大小、列或数据未知,这对于动态构建表很有用。

备注

添加行需要每次生成整个表的新副本,因此对于大型表,这可能会很慢。另一方面,添加列的速度很快。

>>> t = Table()
>>> t['a'] = [1, 4]
>>> t['b'] = [2.0, 5.0]
>>> t['c'] = ['x', 'y']

>>> t = Table(names=('a', 'b', 'c'), dtype=('f4', 'i4', 'S2'))
>>> t.add_row((1, 2.0, 'x'))
>>> t.add_row((4, 5.0, 'y'))

>>> t = Table(dtype=[('a', 'f4'), ('b', 'i4'), ('c', 'S2')])

如果您的数据列具有与其关联的物理单元,则建议您使用 QTable 班级。这将允许将列作为本机列存储在表中 Quantity 并带来最大的力量 单位和数量 (astropy.units ) 坐到桌子上。看见 数量和数量 了解更多细节。**

>>> t = QTable()
>>> t['a'] = [1, 4]
>>> t['b'] = [2.0, 5.0] * u.cm / u.s
>>> t['c'] = ['x', 'y']
>>> type(t['b'])
<class 'astropy.units.quantity.Quantity'>

列列表#

典型的情况是,在不同的变量中定义了许多具有相同长度的数据列。这些可能是Python列表或 numpy 数组或两者的混合。这些可以用来创建 Table 通过将列数据变量放入Python列表中。在这种情况下,列名不是由输入数据定义的,因此必须使用 names 关键字或它们将自动生成为 col<N> .

>>> a = np.array([1, 4], dtype=np.int32)
>>> b = [2.0, 5.0]
>>> c = ['x', 'y']
>>> t = Table([a, b, c], names=('a', 'b', 'c'))
>>> t
<Table length=2>
  a      b     c
int32 float64 str1
----- ------- ----
    1     2.0    x
    4     5.0    y

使用第一个表中的列生成新表

一旦你有了一个 Table ,然后您可以通过选择列并将它们放入一个Python列表中来创建一个新表(例如, [ t['c'], t['a'] ] ):

>>> Table([t['c'], t['a']])
<Table length=2>
 c     a
str1 int32
---- -----
   x     1
   y     4

使用涉及列的表达式生成新表

这个 Column 对象派生自标准 numpy.ndarray 可以直接在算术表达式中使用。这允许以一种紧凑的方式创建具有修改后的列值的新表:

>>> Table([t['a']**2, t['b'] + 10])
<Table length=2>
  a      b
int32 float64
----- -------
    1    12.0
   16    15.0

不同类型的列数据

的列表输入方法 Table 非常灵活,因为您可以混合使用不同的数据类型来初始化表:

>>> a = (1., 4.)
>>> b = np.array([[2, 3], [5, 6]], dtype=np.int64)  # vector column
>>> c = Column(['x', 'y'], name='axis')
>>> d = u.Quantity([([1., 2., 3.], [.1, .2, .3]),
...                 ([4., 5., 6.], [.4, .5, .6])], 'm,m/s')
>>> QTable([a, b, c, d])
<QTable length=2>
  col0    col1   axis          col3 [f0, f1]
                                  (m, m / s)
float64 int64[2] str1     (float64[3], float64[3])
------- -------- ---- -------------------------------
    1.0   2 .. 3    x ([1., 2., 3.], [0.1, 0.2, 0.3])
    4.0   5 .. 6    y ([4., 5., 6.], [0.4, 0.5, 0.6])

请注意,在第三列中,现有的列名 'axis' 使用。

列的Dict#

A dict 的列数据可以用来初始化 Table **

>>> arr = {'a': np.array([1, 4], dtype=np.int32),
...        'b': [2.0, 5.0],
...        'c': ['x', 'y']}
>>>
>>> Table(arr)
<Table length=2>
  a      b     c
int32 float64 str1
----- ------- ----
    1     2.0    x
    4     5.0    y

指定列顺序和可选的数据类型 ::

>>> Table(arr, names=('a', 'c', 'b'), dtype=('f8', 'U2', 'i4'))
<Table length=2>
   a     c     b
float64 str2 int32
------- ---- -----
    1.0    x     2
    4.0    y     5

不同类型的列数据

输入列数据可以是任何可以初始化 Column 对象:

>>> arr = {'a': (1., 4.),
...        'b': np.array([[2, 3], [5, 6]], dtype=np.int64),
...        'c': Column(['x', 'y'], name='axis')}
>>> Table(arr, names=('a', 'b', 'c'))
<Table length=2>
   a       b      c
float64 int64[2] str1
------- -------- ----
    1.0   2 .. 3    x
    4.0   5 .. 6    y

注意钥匙 'c' 优先于现有列名 'axis' 在第三列。还要看看 'b' column是一个向量列,其中每个row元素本身就是一个两元素数组。

无法重命名列 ::

>>> Table(arr, names=('a_new', 'b_new', 'c_new'))
Traceback (most recent call last):
  ...
KeyError: 'a_new'

行数据#

面向行的数据可用于创建使用 rows 关键字参数。

List or tuple of data records

如果有面向行的输入数据(如记录列表),则需要使用 rows 创建表的关键字::

>>> data_rows = [(1, 2.0, 'x'),
...              (4, 5.0, 'y'),
...              (5, 8.2, 'z')]
>>> t = Table(rows=data_rows, names=('a', 'b', 'c'))
>>> print(t)
 a   b   c
--- --- ---
  1 2.0   x
  4 5.0   y
  5 8.2   z

dict对象列表

您还可以使用行值初始化表。它被构造为一个列表 dict 物体。键确定列名::

>>> data = [{'a': 5, 'b': 10},
...         {'a': 15, 'b': 20}]
>>> t = Table(rows=data)
>>> print(t)
 a   b
--- ---
  5  10
 15  20

如果缺少一个或多个键,则标记为缺少一个值:

>>> t = Table(rows=[{'a': 5, 'b': 10}, {'a': 15, 'c': 50}])
>>> print(t)
 a   b   c
--- --- ---
  5  10  --
 15  --  50

属性指定列顺序。 names 论点::

>>> data = [{'a': 5, 'b': 10},
...         {'a': 15, 'b': 20}]
>>> t = Table(rows=data, names=('b', 'a'))
>>> print(t)
 b   a
--- ---
 10   5
 20  15

如果 names ,则列顺序将由第一个 dict 如果它包含所有列的值,或者如果不包含,则按字母顺序对列名进行排序::

>>> data = [{'b': 10, 'c': 7, 'a': 5},
...         {'a': 15, 'c': 35, 'b': 20}]
>>> t = Table(rows=data)
>>> print(t)
 b   c   a
--- --- ---
 10   7   5
 20  35  15
>>> data = [{'b': 10, 'c': 7, },
...         {'a': 15, 'c': 35, 'b': 20}]
>>> t = Table(rows=data)
>>> print(t)
 a   b   c
--- --- ---
 --  10   7
 15  20  35

单行

也可以从现有表的单行生成新表:

>>> a = [1, 4]
>>> b = [2.0, 5.0]
>>> t = Table([a, b], names=('a', 'b'))
>>> t2 = Table(rows=t[1])

记住 Row 与新创建的 Table 它的长度是一。这类似于标量之间的差异 1 (长度0)和一个数组,如 np.array([1]) 长度为1。

备注

如果输入数据是一个DICT列表或单个数据 Table 行,可以将数据作为 data 因为这些形式总是明确无误的。例如, Table([{{'a': 1}}, {{'a': 2}}]) 被接受。但是,必须始终使用 rows 关键字,否则它将被解释为列列表。

NumPy结构化阵列#

这个 structured array 中的标准机制 numpy 用于存储异构表数据。大多数读取表文件的科学I/O包(例如, astropy.io.fits, astropy.io.votable, and asciitable )将在基于结构化数组的对象中返回表。可以使用以下命令创建结构化数组:

>>> arr = np.array([(1, 2.0, 'x'),
...                 (4, 5.0, 'y')],
...                dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'U2')])

arr 可以创建相应的 Table 对象:

>>> Table(arr)
<Table length=2>
  a      b     c
int32 float64 str2
----- ------- ----
    1     2.0    x
    4     5.0    y

请注意,在上面的示例和下面的大多数示例中,我们创建了一个表,并立即请求交互式的Python解释器打印该表,以查看我们生成了什么。在实际代码中,您可能会执行如下操作::

>>> table = Table(arr)
>>> print(table)
 a   b   c
--- --- ---
  1 2.0   x
  4 5.0   y

作为一列的结构化数组#

在某些情况下,将结构化数组作为表中的单个列包括是很方便的。这个 EarthLocation 类是Astery中的一个例子,其中结构化列有三个元素 xyz 。另一个例子是具有值、最小允许值和最大允许值的建模参数。在这里,我们演示如何将前面定义为列的简单结构化数组包括在内:

>>> table = Table()
>>> table['name'] = ['Micah', 'Mazzy']
>>> table['arr'] = arr
>>> print(table)
 name arr [a, b, c]
----- -------------
Micah  (1, 2., 'x')
Mazzy  (4, 5., 'y')

您可以访问或打印结构化列中的单个字段,如下所示:

>>> print(table['arr']['b'])
[2. 5.]

新列名

通过提供 names 论点:

>>> Table(arr, names=('a_new', 'b_new', 'c_new'))
<Table length=2>
a_new  b_new  c_new
int32 float64  str2
----- ------- -----
    1     2.0     x
    4     5.0     y

新数据类型

每个列的数据类型也可以用 dtype ::

>>> Table(arr, dtype=('f4', 'i4', 'U4'))
<Table length=2>
   a      b    c
float32 int32 str4
------- ----- ----
    1.0     2    x
    4.0     5    y

>>> Table(arr, names=('a_new', 'b_new', 'c_new'), dtype=('f4', 'i4', 'U4'))
<Table length=2>
 a_new  b_new c_new
float32 int32  str4
------- ----- -----
    1.0     2     x
    4.0     5     y

NumPy齐次阵列#

A numpy 一维数组被视为单行表,其中数组的每个元素对应于一列::

>>> Table(np.array([1, 2, 3]), names=['a', 'b', 'c'], dtype=('i8', 'i8', 'i8'))
<Table length=1>
  a     b     c
int64 int64 int64
----- ----- -----
    1     2     3

A numpy 二维数组(其中所有元素都具有相同的类型)也可以转换为 Table 。在这种情况下,列名不是由数据指定的,必须由用户提供或将自动生成为 col<N> 哪里 <N> 是列号。

自动列名的基本示例 ::

>>> arr = np.array([[1, 2, 3],
...                 [4, 5, 6]], dtype=np.int32)
>>> Table(arr)
<Table length=2>
 col0  col1  col2
int32 int32 int32
----- ----- -----
    1     2     3
    4     5     6

指定的列名和类型 ::

>>> Table(arr, names=('a_new', 'b_new', 'c_new'), dtype=('f4', 'i4', 'U4'))
<Table length=2>
 a_new  b_new c_new
float32 int32  str4
------- ----- -----
    1.0     2     3
    4.0     5     6

引用原始数据

只要数据类型未更改,就可以引用原始数据:

>>> t = Table(arr, copy=False)

请参阅 Copy versus Reference 部分了解更多信息。

Python arrays versus NumPy arrays as input

有一个稍微微妙的问题,重要的是要理解这种方式 Table 将创建对象。任何看起来像Python的数据输入 list (包括 tuple )被认为是列的列表。相比之下,同质化的 numpy.ndarray 输入被解释为行列表::

>>> arr = [[1, 2, 3],
...        [4, 5, 6]]
>>> np_arr = np.array(arr)

>>> print(Table(arr))    # Two columns, three rows
col0 col1
---- ----
   1    4
   2    5
   3    6

>>> print(Table(np_arr))  # Three columns, two rows
col0 col1 col2
---- ---- ----
   1    2    3
   4    5    6

需要这种二分法来支持灵活的列表输入,同时保留2D的自然解释 numpy 数组,其中第一个索引对应于数据“行”,第二个索引对应于数据“列”。

从现有表#

可以通过选择现有表中的列子集来创建新表:

>>> t = Table(names=('a', 'b', 'c'))
>>> t['c', 'b', 'a']  # Makes a copy of the data
<Table length=0>
   c       b       a
float64 float64 float64
------- ------- -------

另一种方法是使用 columns 属性(在 TableColumns 节)来初始化新表。这使您可以根据列的数字索引或名称选择列,并支持切片语法:

>>> Table(t.columns[0:2])
<Table length=0>
   a       b
float64 float64
------- -------

>>> Table([t.columns[0], t.columns['c']])
<Table length=0>
   a       c
float64 float64
------- -------

要创建空(没有行)的现有表的副本,请执行以下操作:

>>> t = Table([[1.0, 2.3], [2.1, 3]], names=['x', 'y'])
>>> t
<Table length=2>
   x       y
float64 float64
------- -------
    1.0     2.1
    2.3     3.0

>>> tcopy = t[:0].copy()
>>> tcopy
<Table length=0>
   x       y
float64 float64
------- -------

已知大小的空数组#

如果您确实知道表的大小,但事先不知道值,则可以创建一个归零的 numpy.ndarray 并构建 Table 出自:

>>> N = 3
>>> dtype = [('a', 'i4'), ('b', 'f8'), ('c', 'bool')]
>>> t = Table(data=np.zeros(N, dtype=dtype))
>>> t
<Table length=3>
  a      b      c
int32 float64  bool
----- ------- -----
    0     0.0 False
    0     0.0 False
    0     0.0 False

例如,您可以使用从另一个表中提取或动态生成的值逐行填充此表:

>>> for i in range(len(t)):
...     t[i] = (i, 2.5*i, i % 2)
>>> t
<Table length=3>
  a      b      c
int32 float64  bool
----- ------- -----
    0     0.0 False
    1     2.5  True
    2     5.0 False

SkyCoord#

A SkyCoord 对象可以转换为 QTable 使用ITS to_table() 方法。有关详细信息和示例,请参阅 将SkyCoord转换为表格

Pandas数据帧#

关于以下内容的部分 与Pandas套餐对接 提供有关如何初始化 Table 使用 pandas.DataFrame 通过 from_pandas() 类方法。这提供了一种方便的方式来利用中的许多I/O和表操作方法 pandas

注释行#

ASCII文件中的注释行可以通过 'comments' 表中的键。以下命令将在输出ASCII文件中插入两个注释行,除非 comment=False 在中显式设置 write() ::

>>> import sys
>>> from astropy.table import Table
>>> t = Table(names=('a', 'b', 'c'), dtype=('f4', 'i4', 'S2'))
>>> t.add_row((1, 2.0, 'x'))
>>> t.meta['comments'] = ['Here is my explanatory text. This is awesome.',
...                       'Second comment line.']
>>> t.write(sys.stdout, format='ascii')
# Here is my explanatory text. This is awesome.
# Second comment line.
a b c
1.0 2 x

初始化详细信息#

表对象是通过初始化 Table 使用以下参数初始化对象,这些参数都是可选的:

data : numpy.ndarray, dictlistTable ,或表状对象,可选Ndarray、dict、List、Table或表状对象,可选

初始化表的数据。

masked : bool ,可选可选的布尔

指定是否屏蔽表。

names : list ,可选可选列表

指定列名。

dtype : list ,可选可选列表

指定列数据类型。

meta : dict ,可选可选的

与表关联的元数据。

copy : bool ,可选可选的布尔

复制输入数据。如果输入是 Table 这个 meta 总是被复制,而不考虑 copy 参数。缺省值为 True

rows : numpy.ndarray, list 列表数量,可选Ndarray,列表列表,可选

表的面向行的数据,而不是 data 争论。

copy_indices : bool ,可选可选的布尔

复制输入数据中的所有索引。缺省值为 True

units : listdict ,可选列表、dict、可选

应用于列的单位的列表或dict。

descriptions : listdict ,可选列表、dict、可选

应用于列的描述的列表或dict。

**kwargs : dict ,可选可选的

转换类表对象时的其他关键字参数。

下面的小节提供了有关每个关键字参数的值和选项的进一步详细信息,这些关键字参数可用于创建新的 Table 对象。

数据#

这个 Table 对象可以用几种不同的形式初始化 data 争论。

NumPy ndarray (structured array)

基列名是 data 结构化数组。这个 names list(可选)可用于选择特定字段和/或重新排序基名称。这个 dtype 列表(可选)的长度必须与 names 并用于覆盖现有 data 类型。

NumPy ndarray (homogeneous)

如果 data 是一维的 numpy.ndarray 然后将其视为单行表,其中数组的每个元素对应于一列。

如果 data 至少是一个二维的 numpy.ndarray ,则第一个(最左侧)索引对应于行号(表格长度),第二个索引对应于列号(表格宽度)。更高的维度被吸收在每个表格单元的形状中。

如果提供,则 names 列表必须与 data 争论。的默认值 names 在表单中自动生成列名 col<N> . 如果提供,则 dtype 列表重写基列类型,并且必须与 names .

dict-like

的关键字 data 对象定义基列名称。相应的值可以是 Column 对象, numpy 数组或类似列表的对象。这个 names 列表(可选)可用于选择特定字段和/或重新排序基本名称。这个 dtype 列表(可选)的长度必须与 names 并用于覆盖现有或默认数据类型。

list-like

中的每一项 data List提供数据值的列,可以是 Column 对象, numpy.ndarray ,或类似列表的对象。这个 names 列表定义了每列的名称。如果未提供名称,则将自动生成这些名称(使用 names 论据或通过 Column 对象)。如果提供,则 names 参数必须与 data 单子。可选的 dtype 列表将覆盖现有或默认数据类型,并且必须匹配 names 在篇幅上。

list-of-dicts

类似于Python的内置 csv.DictReader 中的每一项 data List提供一行数据值,并且必须是 dict 。每个文件中的键值 dict 定义列名。这个 names 可以提供参数来指定列排序。如果 names ,则列顺序将由第一个 dict 如果它包含所有列的值,则按字母顺序对列名排序,如果不包含,则按字母顺序对列名进行排序。这个 dtype 可以指定列表,并且必须与输出列的顺序相对应。

Table-like object

如果另一个表状对象有一个 __astropy_table__() 方法,则可以使用该对象直接创建 Table 。请参阅 table-like objects 部分了解详细信息。

None

初始化零长度表。如果 names 任选地 dtype ,然后创建相应的列。

姓名#

这个 names 参数提供了一种指定表列名称或重写现有列名的方法。缺省情况下,列名取自现有名称(对于 numpy.ndarrayTable 输入)或自动生成为 col<N> 。如果 names 则它必须是长度与列数相同的列表。任何具有值的列表元素 None 回退到默认名称。

在以下情况下 data 是作为 dict 在列中, names 可以提供参数来指定列的顺序。这个 names 然后,列表中必须包含 data dict

D型#

这个 dtype 参数提供了一种指定表列数据类型或覆盖现有类型的方法。默认情况下,这些类型要么取自现有类型(对于 numpy.ndarrayTable 输入)或由 numpy.array() 例行公事。如果 dtype 则它必须是长度与列数相同的列表。值必须有效 numpy.dtype 初始化器或 None 。任何具有值的列表元素 None 回退到默认类型。

#

这个 meta 参数是包含与表关联的元数据的对象。建议将此对象设置为 dictOrderedDict ,但唯一严格的要求是它可以与标准库一起复制 copy.deepcopy() 例行公事。默认情况下, meta 是一个空洞的 OrderedDict

复制#

在以下情况下 data 要么是一个 numpy.ndarray 对象,则为 dict ,或现有的 Table ,可以通过设置来使用对现有数据的引用 copy=False 。这具有减少内存使用和速度更快的优势。但是,您应该小心,因为对新的 Table 在原始输入数据中也会看到数据。请参阅 Copy versus Reference 部分了解更多信息。

#

此参数允许将数据作为行序列提供,与 data 关键字,它通常假定数据是一个列序列。这个 Row data 部分提供了详细信息。

copy_indices#

如果您正在初始化 Table 从另一个人 Table 这充分利用了 表索引 ,则此选项允许复制该表 without 通过设置复制索引 copy_indices=False 。默认情况下,将复制索引。

单位#

这允许在创建表时为一个或多个列设置单位。输入可以是与表中的每一列对应的单位值列表(使用 None'' 表示无单位),或 dict 它为指定的列名提供单位。例如::

>>> dat = [[1, 2], ['hello', 'world']]
>>> qt = QTable(dat, names=['a', 'b'], units=(u.m, None))
>>> qt = QTable(dat, names=['a', 'b'], units={'a': u.m})

看见 数量和数量 关于我们为什么使用 QTable 在这里,不是 Table

描述#

这允许在创建表时设置一个或多个列的描述。输入可以是与表中的每一列相对应的描述值列表(使用 None 用于无描述),或 dict 它提供指定列名的说明。它的工作方式与 units 上面的例子。

复制与引用#

通常情况下,当新的 Table 对象,则输入数据是 copied 。这确保了如果修改新的表元素,则原始数据不会受到影响。但是,当从现有的 Table 一种 numpy.ndarray 对象(结构化或同构)或 dict ,则可以禁用复制,以便改为使用对原始数据的存储器引用。这样做的优点是速度更快,使用的内存更少。但是,需要注意的是,新的表格数据和原始数据是链接的,如下所示:

>>> arr = np.array([(1, 2.0, 'x'),
...                 (4, 5.0, 'y')],
...                dtype=[('a', 'i8'), ('b', 'f8'), ('c', 'S2')])
>>> print(arr['a'])  # column "a" of the input array
[1 4]
>>> t = Table(arr, copy=False)
>>> t['a'][1] = 99
>>> print(arr['a'])  # arr['a'] got changed when we modified t['a']
[ 1 99]

请注意,当引用数据时,不可能更改数据类型,因为该操作需要制作数据的副本。在这种情况下,会发生错误:

>>> t = Table(arr, copy=False, dtype=('f4', 'i4', 'S4'))
Traceback (most recent call last):
  ...
ValueError: Cannot specify dtype when copy=False

使用被引用数据的另一个警告是,如果向表中添加新行,对原始数据数组的引用将丢失,而表现在将保留原始值的副本(除了新行)。

Column和TableColumns类#

有两个班, ColumnTableColumns ,这在构造新表时非常有用。

#

A Column 对象可以按如下方式创建,在所有情况下,列 name 应作为关键字参数提供,并且您可以选择提供以下值:

data列表、ndarray或None

列数据值。

dtype : numpy.dtype 兼容值数字.dtype兼容值

列的数据类型。

descriptionSTR

列的完整描述。

unitSTR

物理单位。

format : str 或函数STR或函数

Format specifier 用于输出列值。

meta双关语

与列关联的元数据。

初始化选项#

列数据值、形状和数据类型通过以下两种方式之一指定:

Provide data but not length or shape

实例:

col = Column([1, 2], name='a')  # shape=(2,)
col = Column([[1, 2], [3, 4]], name='a')  # shape=(2, 2)
col = Column([1, 2], name='a', dtype=float)
col = Column(np.array([1, 2]), name='a')
col = Column(['hello', 'world'], name='a')

这个 dtype 参数可以是任何值,该值是 numpy.dtype 。请参阅参考资料 data type objects 。示例包括:

  • Python非字符串类型 (floatintbool )。

  • numpy 非字符串类型(例如, np.float32np.int64 )。

  • numpy.dtype 数组协议类型字符串(例如, 'i4''f8''U15' )。

如果没有 dtype 值,则使用 numpy.array() 。什么时候 data 被提供,则 shapelength 参数将被忽略。

Provide length and optionally shape, but not data

实例:

col = Column(name='a', length=5)
col = Column(name='a', dtype=int, length=10, shape=(3,4))

默认设置 dtypenp.float64 。这个 shape 参数是列中单个单元格的数组形状。默认设置 shape() 这意味着每个元素中都有一个值。

备注

为列设置类型后,无法更改该类型。如果将不同类型的数据值分配给列,则它们将转换为现有的列类型。

格式说明符#

当表或列被打印或写入ASCII表时,格式说明符控制列值的输出。在最简单的情况下,它是一个可以传递给Python的内置的字符串 format() 功能。对于更复杂的格式,还可以给出“old style”或“new style”格式字符串,甚至可以给出一个函数:

普通格式规范

此类型的字符串直接指定如何使用 format specification mini-language 这和C很相似。

".4f" 将在小数点后以浮点格式给出四位数,或

"6d" 将给出六个字符字段中的整数。

旧格式字符串

这对应于如下语法 "%.4f" % value 如中所述 printf-style String Formatting .

"%.4f" 以浮点格式打印小数点后的四位数字,或

"%6d" 在六个字符宽的字段中打印整数。

新样式格式字符串

这对应于如下语法 "{{:.4f}}".format(value) 如中所述 format string syntax .

"{{:.4f}}" 以浮点格式打印小数点后的四位数字,或

"{{:6d}}" 在六个字符宽的字段中打印整数。

请注意,在这两种格式字符串中,只格式化一个值的任何Python字符串都是有效的,因此 {{:.4f}} angstromsValue: %12.2f 两者都可以。

Function

通过设置格式化功能可以实现最大的灵活性。此函数必须接受单个参数(值)并返回一个字符串。需要注意的是,这样的格式化函数不能保存到文件中,如果您尝试这样做,将会得到一个异常。在下面的示例中,这用于生成LaTeX就绪输出:

>>> t = Table([[1,2],[1.234e9,2.34e-12]], names = ('a','b'))
>>> def latex_exp(value):
...     val = f'{value:8.2}'
...     mant, exp = val.split('e')
...     # remove leading zeros
...     exp = exp[0] + exp[1:].lstrip('0')
...     return f'$ {mant} \\times 10^{{ {exp} }}$'
>>> t['b'].format = latex_exp
>>> t['a'].format = '.4f'
>>> import sys
>>> t.write(sys.stdout, format='latex')
\begin{table}
\begin{tabular}{cc}
a & b \\
1.0000 & $  1.2 \times 10^{ +9 }$ \\
2.0000 & $  2.3 \times 10^{ -12 }$ \\
\end{tabular}
\end{table}

Format string for structured array column

对于结构化数组的列,格式字符串必须是使用 "new style" format strings 其中参数替换对应于结构化数组中的字段名。看见 结构化数组列 举个例子。

TableColumns#

Table 对象具有属性 columns 它是一个有序字典,它存储 Column 表中的对象(另请参见 Column 第节)。从技术上讲 columns 属性是 TableColumns 对象,这是一个增强的有序字典,它提供了选择多个列的更简单的方法。有几点需要记住:

有几种不同的方法可以从 TableColumns 对象:

按名称选择列 ::

>>> t = Table(names=('a', 'b', 'c', 'd'))

>>> t.columns['d', 'c', 'b']
<TableColumns names=('d','c','b')>

按索引切片选择列 ::

>>> t.columns[0:2]  # Select first two columns
<TableColumns names=('a','b')>

>>> t.columns[::-1]  # Reverse column order
<TableColumns names=('d','c','b','a')>

Select single columns by index or name **

>>> t.columns[1]  # Choose a column by index
<Column name='b' dtype='float64' length=0>

>>> t.columns['b']  # Choose a column by name
<Column name='b' dtype='float64' length=0>

子类化表#

对于某些应用程序,将 Table 为了引入专门的行为。在这里,我们讨论了两个特殊的子类化用例:添加自定义表属性和更改内部类对象的行为。

添加自定义表属性#

一个很有用的简单定制是向table对象添加新属性。例如,没有什么可以阻止在现有表对象上设置属性 t.foo = 'hello' . 但是,该属性将是短暂的,因为如果对表进行切片、复制或pickle操作,它将丢失。相反,您可以添加持久属性,如下例所示:

from astropy.table import Table, TableAttribute

class MyTable(Table):
    foo = TableAttribute()
    bar = TableAttribute(default=[])
    baz = TableAttribute(default=1)

t = MyTable([[1, 2]], foo='foo')
t.bar.append(2.0)
t.baz = 'baz'

一些关键点:

  • 可以在创建表时或使用设置对象属性的常用语法设置自定义属性。

  • 自定义属性始终具有缺省值,要么在类定义中显式设置,要么 None

  • 属性值存储在表中 meta 字典。这是一种通过复制、切片和序列化(如酸洗或写入 ECSV格式 文件。

更改内部类对象的行为#

还可以更改内部类对象的行为,这些对象由 Table 。这包括行、列、格式和列容器。为此,子类需要声明要使用的类(如果它与内置版本不同)。这是通过指定一个或多个类属性来完成的 RowColumnMaskedColumnTableColumns ,或 TableFormatter

下面这个简单的示例使用“不做任何事”子类覆盖所有这些子类,但实际上您将只重写必需的子组件:

>>> from astropy.table import Table, Row, Column, MaskedColumn, TableColumns, TableFormatter

>>> class MyRow(Row): pass
>>> class MyColumn(Column): pass
>>> class MyMaskedColumn(MaskedColumn): pass
>>> class MyTableColumns(TableColumns): pass
>>> class MyTableFormatter(TableFormatter): pass

>>> class MyTable(Table):
...     """
...     Custom subclass of astropy.table.Table
...     """
...     Row = MyRow  # Use MyRow to create a row object
...     Column = MyColumn  # Column
...     MaskedColumn = MyMaskedColumn  # Masked Column
...     TableColumns = MyTableColumns  # Ordered dict holding Column objects
...     TableFormatter = MyTableFormatter  # Controls table output

例子#

举一个更实际的例子,假设您有一个数据表,其中包含一组固定的列,但您还希望为每行携带一个任意的参数字典,然后使用相同的项访问语法访问这些值,就像它们是列一样。这里假设额外的参数包含在 numpy 名为的对象-数据类型列 params **

>>> from astropy.table import Table, Row
>>> class ParamsRow(Row):
...    """
...    Row class that allows access to an arbitrary dict of parameters
...    stored as a dict object in the ``params`` column.
...    """
...    def __getitem__(self, item):
...        if item not in self.colnames:
...            return super().__getitem__('params')[item]
...        else:
...            return super().__getitem__(item)
...
...    def keys(self):
...        out = [name for name in self.colnames if name != 'params']
...        params = [key.lower() for key in sorted(self['params'])]
...        return out + params
...
...    def values(self):
...        return [self[key] for key in self.keys()]

现在我们用一个微不足道的 Table 子类::

>>> class ParamsTable(Table):
...     Row = ParamsRow

首先创建一个表并添加几行:

>>> t = ParamsTable(names=['a', 'b', 'params'], dtype=['i', 'f', 'O'])
>>> t.add_row((1, 2.0, {'x': 1.5, 'y': 2.5}))
>>> t.add_row((2, 3.0, {'z': 'hello', 'id': 123123}))
>>> print(t)
 a   b             params
--- --- ----------------------------
  1 2.0         {'x': 1.5, 'y': 2.5}
  2 3.0 {'z': 'hello', 'id': 123123}

现在看看我们的专业 ParamsRow 对象:

>>> t[0]['y']
2.5
>>> t[1]['id']
123123
>>> t[1].keys()
['a', 'b', 'id', 'z']
>>> t[1].values()
[2, 3.0, 123123, 'hello']

要使此示例真正有用,您可能需要重写 Table.__getitem__() 以便允许对参数字段的表级访问。这可能类似于::

class ParamsTable(table.Table):
    Row = ParamsRow

    def __getitem__(self, item):
        if isinstance(item, str):
            if item in self.colnames:
                return self.columns[item]
            else:
                # If item is not a column name then create a new MaskedArray
                # corresponding to self['params'][item] for each row.  This
                # might not exist in some rows so mark as masked (missing) in
                # those cases.
                mask = np.zeros(len(self), dtype=np.bool_)
                item = item.upper()
                values = [params.get(item) for params in self['params']]
                for ii, value in enumerate(values):
                    if value is None:
                        mask[ii] = True
                        values[ii] = ''
                return self.MaskedColumn(name=item, data=values, mask=mask)

        # ... and then the rest of the original __getitem__ ...

列和数量#

astropy Quantity 可以用两种互补的方式在表中处理对象。第一种方法存储 Quantity 通过“mixin”列协议在表中本机生成对象。请参见 混合柱数量和数量 简单地说,关键区别在于使用 QTable 类来指示 Quantity 应以本机方式存储在表中:

>>> from astropy.table import QTable
>>> from astropy import units as u
>>> t = QTable()
>>> t['velocity'] = [3, 4] * u.m / u.s
>>> type(t['velocity'])
<class 'astropy.units.quantity.Quantity'>

对于数量敏感的新代码,我们建议使用 QTable ,但这可能并非在所有情况下都可能实现(尤其是在与不处理数量的遗留代码接口时),而且 细节和注意事项 这是适用的。在这种情况下,使用 Table 类,它将转换 Quantity 到A Column 对象与A unit 属性:

>>> from astropy.table import Table
>>> t = Table()
>>> t['velocity'] = [3, 4] * u.m / u.s
>>> type(t['velocity'])
<class 'astropy.table.column.Column'>
>>> t['velocity'].unit
Unit("m / s")

了解有关使用标准的更多信息 Column 具有定义单位的对象,请参见 带单位的列 部分。

桌状物体#

In order to improve interoperability between different table classes, an astropy Table object can be created directly from any other table-like object that provides an __astropy_table__() method. In this case the __astropy_table__() method will be called as follows:

>>> data = SomeOtherTableClass({'a': [1, 2], 'b': [3, 4]})  
>>> t = QTable(data, copy=False, mask_invalid=True)  

Internally the following call will be made to ask the data object to return a representation of itself as an astropy Table, respecting the copy preference of the original call to QTable():

data.__astropy_table__(cls, copy, **kwargs)

这里 clsTable 正在实例化的类或子类( QTable 在该示例中), copy 中的值的副本 data 应提供,并且 **kwargs 是否有任何无效的额外关键字参数 Table __init__() 关键字参数。在上面的示例中, mask_invalid=True 最终会出现在 **kwargs 并被传递到 __astropy_table__()

该实现可以选择允许附加的关键字参数(例如, mask_invalid 它通过 **kwargs )。

作为一个简洁的例子,假设一个基于dict的表类。(请注意 Table 已经可以从dict-like对象初始化,所以这有点做作,但说明了所涉及的原理。)请注意方法签名::

def __astropy_table__(self, cls, copy, **kwargs):

这个的类实现必须使用 **kwargs 在结尾捕获关键字参数的技术。这是为了确保将来的兼容性,以防向内部添加其他关键字 table = data.__astropy_table__(cls, copy) 打电话。包括 **kwargs 在这种情况下可以防止破损。:

class DictTable(dict):
    """
    Trivial "table" class that just uses a dict to hold columns.
    This does not actually implement anything useful that makes
    this a table.

    The non-standard ``mask_invalid=False`` keyword arg here will be passed
    via the **kwargs of Table __init__().
    """

    def __astropy_table__(self, cls, copy, mask_invalid=False, **kwargs):
        """
        Return an astropy Table of type ``cls``.

        Parameters
        ----------
        cls : type
             Astropy ``Table`` class or subclass.
        copy : bool
             Copy input data (True) or return a reference (False).
        mask_invalid : bool, optional
             Controls whether invalid values (NaNs) should be masked.
             Default is False.
        **kwargs : dict, optional
             Additional keyword args (ignored currently).
        """
        if kwargs:
            warnings.warn(f'unexpected keyword args {kwargs}')

        cols = list(self.values())
        names = list(self.keys())

        if mask_invalid:
            cols = [
                Masked(col, mask=mask) if np.any(mask := np.isnan(col)) else col
                for col in cols
            ]

        return cls(cols, names=names, copy=copy)