构造表#
表的初始构造方式具有很大的灵活性。输入的详细信息 Table
和 QTable
构造函数在 Initialization Details 第节。然而,理解如何制作表格的最好方法是通过示例。
实例#
安装程序#
对于以下示例,您需要导入 QTable
, Table
和 Column
类和 单位和数量 (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#
>>> 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中的一个例子,其中结构化列有三个元素 x
, y
和 z
。另一个例子是具有值、最小允许值和最大允许值的建模参数。在这里,我们演示如何将前面定义为列的简单结构化数组包括在内:
>>> 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 。
初始化详细信息#
表对象是通过初始化 Table
使用以下参数初始化对象,这些参数都是可选的:
data
:numpy.ndarray
,dict
,list
,Table
,或表状对象,可选Ndarray、dict、List、Table或表状对象,可选初始化表的数据。
masked
:bool
,可选可选的布尔指定是否屏蔽表。
names
:list
,可选可选列表指定列名。
dtype
:list
,可选可选列表指定列数据类型。
meta
:dict
,可选可选的与表关联的元数据。
copy
:bool
,可选可选的布尔rows
:numpy.ndarray
,list
列表数量,可选Ndarray,列表列表,可选表的面向行的数据,而不是
data
争论。copy_indices
:bool
,可选可选的布尔复制输入数据中的所有索引。缺省值为
True
。units
:list
,dict
,可选列表、dict、可选应用于列的单位的列表或dict。
descriptions
:list
,dict
,可选列表、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.ndarray
或 Table
输入)或自动生成为 col<N>
。如果 names
则它必须是长度与列数相同的列表。任何具有值的列表元素 None
回退到默认名称。
在以下情况下 data
是作为 dict
在列中, names
可以提供参数来指定列的顺序。这个 names
然后,列表中必须包含 data
dict
。
D型#
这个 dtype
参数提供了一种指定表列数据类型或覆盖现有类型的方法。默认情况下,这些类型要么取自现有类型(对于 numpy.ndarray
或 Table
输入)或由 numpy.array()
例行公事。如果 dtype
则它必须是长度与列数相同的列表。值必须有效 numpy.dtype
初始化器或 None
。任何具有值的列表元素 None
回退到默认类型。
元#
这个 meta
参数是包含与表关联的元数据的对象。建议将此对象设置为 dict
或 OrderedDict
,但唯一严格的要求是它可以与标准库一起复制 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})
描述#
这允许在创建表时设置一个或多个列的描述。输入可以是与表中的每一列相对应的描述值列表(使用 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类#
有两个班, Column
和 TableColumns
,这在构造新表时非常有用。
柱#
A Column
对象可以按如下方式创建,在所有情况下,列 name
应作为关键字参数提供,并且您可以选择提供以下值:
data
列表、ndarray或None列数据值。
dtype
:numpy.dtype
兼容值数字.dtype兼容值列的数据类型。
description
STR列的完整描述。
unit
STR物理单位。
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 。示例包括:
numpy
非字符串类型(例如,np.float32
,np.int64
)。
numpy.dtype
数组协议类型字符串(例如,'i4'
,'f8'
,'U15'
)。如果没有
dtype
值,则使用numpy.array()
。什么时候data
被提供,则shape
和length
参数将被忽略。
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))默认设置
dtype
是np.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}} angstroms
或 Value: %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
对象,这是一个增强的有序字典,它提供了选择多个列的更简单的方法。有几点需要记住:
A
Table
可以从TableColumns
对象 (copy
永远都是True
)。从中选择多个列
TableColumns
对象返回另一个TableColumns
对象。从列表中选择一列
TableColumns
对象返回一个Column
。
有几种不同的方法可以从 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'
一些关键点:
更改内部类对象的行为#
还可以更改内部类对象的行为,这些对象由 Table
。这包括行、列、格式和列容器。为此,子类需要声明要使用的类(如果它与内置版本不同)。这是通过指定一个或多个类属性来完成的 Row
, Column
, MaskedColumn
, TableColumns
,或 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")
桌状物体#
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)
这里 cls
是 Table
正在实例化的类或子类( 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)
注释行#
ASCII文件中的注释行可以通过
'comments'
表中的键。以下命令将在输出ASCII文件中插入两个注释行,除非comment=False
在中显式设置write()
::