修改表#

中的数据值 Table 对象的修改方式与 numpy structured arrays 通过访问数据的列或行并适当地赋值。提供的一个关键增强功能 Table 类是修改表结构的能力:您可以添加或删除列,以及添加新的数据行。

快速概述#

下面的代码显示了修改表及其数据的基础知识。

实例#

做一张桌子 ::

>>> from astropy.table import Table
>>> import numpy as np
>>> arr = np.arange(15).reshape(5, 3)
>>> t = Table(arr, names=('a', 'b', 'c'), meta={'keywords': {'key1': 'val1'}})

修改数据值 ::

>>> t['a'][:] = [1, -2, 3, -4, 5]  # Set all values of column 'a'
>>> t['a'][2] = 30                 # Set row 2 of column 'a'
>>> t[1] = (8, 9, 10)              # Set all values of row 1
>>> t[1]['b'] = -9                 # Set column 'b' of row 1
>>> t[0:3]['c'] = 100              # Set column 'c' of rows 0, 1, 2

请注意 table[row][column] 作业不适用于 numpy “花哨” row 索引(在这种情况下 table[row] 将是一种 copy 而不是一个 view )。《花哨》 numpy 指数包括 listnumpy.ndarray ,或 tuplenumpy.ndarray (例如,从 numpy.where() ):

>>> t[[1, 2]]['a'] = [3., 5.]             # doesn't change table t
>>> t[np.array([1, 2])]['a'] = [3., 5.]   # doesn't change table t
>>> t[np.where(t['a'] > 3)]['a'] = 3.     # doesn't change table t

而是使用 table[column][row] 顺序:

>>> t['a'][[1, 2]] = [3., 5.]
>>> t['a'][np.array([1, 2])] = [3., 5.]
>>> t['a'][np.where(t['a'] > 3)] = 3.

也可以使用修改数据列 unit 以一种遵循 Quantity 通过使用 quantity 属性:

>>> from astropy import units as u
>>> tu = Table([[1, 2.5]], names=('a',))
>>> tu['a'].unit = u.m
>>> tu['a'].quantity[:] = [1, 2] * u.km
>>> tu['a']
<Column name='a' dtype='float64' unit='m' length=2>
1000.0
2000.0

备注

组合的最佳方式是将 TableQuantity 类的目的是使用 QTable 。看见 数量和数量 以获取更多信息。

添加一个或多个列

可以使用类似于将键-值对添加到 dict 。右侧的值可以是 listnumpy.ndarray 正确的大小,或将为 broadcast **

>>> t['d1'] = np.arange(5)
>>> t['d2'] = [1, 2, 3, 4, 5]
>>> t['d3'] = 6  # all 5 rows set to 6

要获得更明确的控制,请使用 add_column()add_columns() 方法可用于向表中添加一列或多列。在这两种情况下,新列(S)都可以指定为 listnumpy.ndarrayColumnMaskedColumn ,或标量::

>>> from astropy.table import Column
>>> t.add_column(np.arange(5), name='aa', index=0)  # Insert before first table column
>>> t.add_column(1.0, name='bb')  # Add column of all 1.0 to end of table
>>> c = Column(np.arange(5), name='e')
>>> t.add_column(c, index=0)  # Add Column using the existing column name 'e'
>>> t.add_columns([[1, 2, 3, 4, 5], ['v', 'w', 'x', 'y', 'z']], names=['h', 'i'])

最后,还可以从添加列 Quantity 对象,这会自动设置 unit 属性(但您可能会发现添加一个 Quantity 到一个 QTable 相反,请参见 数量和数量 有关详情):

>>> from astropy import units as u
>>> t['d'] = np.arange(1., 6.) * u.m
>>> t['d']
<Column name='d' dtype='float64' unit='m' length=5>
1.0
2.0
3.0
4.0
5.0

删除列

要从表中删除列,请执行以下操作:

>>> t.remove_column('d1')
>>> t.remove_columns(['aa', 'd2', 'e'])
>>> del t['d3']
>>> del t['h', 'i']
>>> t.keep_columns(['a', 'b'])

替换列

通过将列设置为可用于初始化表列的任何对象(例如, listnumpy.ndarray )。例如,您可以更改 a 列自 intfloat 使用::

>>> t['a'] = t['a'].astype(float)

如果右侧的值不是列状的,则使用 broadcasting 将完成,例如::

>>> t['a'] = 1  # Internally does t['a'][:] = 1

Perform a dictionary-style update

可以执行字典样式的更新,将新列添加到表中并替换现有列:

>>> t1 = Table({'name': ['foo', 'bar'], 'val': [0., 0.]}, meta={'n': 2})
>>> t2 = Table({'val': [1., 2.], 'val2': [10., 10.]}, meta={'id': 0})
>>> t1 |= t2
>>> t1
<Table length=2>
name   val     val2
str3 float64 float64
---- ------- -------
 foo     1.0    10.0
 bar     2.0    10.0

使用时 |= ,则另一个对象不需要是 Table ,它可以是任何可以用来 构造表 具有兼容的行数::

>>> t1 = Table({'name': ['foo', 'bar'], 'val': [0., 0.]}, meta={'n': 2})
>>> d = dict({'val': [1., 2.], 'val2': [10., 10.]})
>>> t1 |= d
>>> t1
<Table length=2>
name   val     val2
str3 float64 float64
---- ------- -------
 foo     1.0    10.0
 bar     2.0    10.0

也可以使用 | 用于合并多个 Table 实例添加到新表中:

>>> from astropy.table import QTable
>>> t1 = Table({'name': ['foo', 'bar'], 'val': [0., 0.]}, meta={'n': 2})
>>> t2 = QTable({'val': [1., 2.], 'val2': [10., 10.]}, meta={'id': 0})
>>> t3 = t1 | t2  # Create a new table as result of update
>>> t3
<Table length=2>
name   val     val2
str3 float64 float64
---- ------- -------
 foo     1.0    10.0
 bar     2.0    10.0

||= 也默默地照顾着 合并元数据 **

>>> t3.meta
{'n': 2, 'id': 0}

更新后的 Table 将会是原件的复制品。如果您需要它们作为参考,您可以使用 update() 方法: copy=False ,见 复制与引用 了解更多细节。

Ensure the existence of a column

Table 有一个 setdefault() 方法,它类似于 dict.setdefault() 。如果表中不存在具有给定名称的列,它会将该列添加到表中。将验证传递给该方法的默认值,并在必要时进行转换。无论采用哪种方式,都会返回表中的(可能是刚刚插入的)列::

>>> t0 = Table({"a": ["Ham", "Spam"]})
>>> t0
<Table length=2>
 a
str4
----
 Ham
Spam
>>> t0.setdefault("a", ["Breakfast"])  # Existing column
<Column name='a' dtype='str4' length=2>
 Ham
Spam
>>> t0.setdefault("approved", False)  # New column
<Column name='approved' dtype='bool' length=2>
False
False
>>> t0
<Table length=2>
 a   approved
str4   bool
---- --------
 Ham    False
Spam    False

重命名列

要重命名列:

>>> t.rename_column('a', 'a_new')
>>> t['b'].name = 'b_new'

添加一行数据

添加行:

>>> t.add_row([-8, -9])

删除行

删除行:

>>> t.remove_row(0)
>>> t.remove_rows(slice(4, 5))
>>> t.remove_rows([1, 2])

按一列或多列排序

要对列排序:

>>> t.sort('b_new')
>>> t.sort(['a_new', 'b_new'])

反转表格行

要反转表行顺序,请执行以下操作:

>>> t.reverse()

修改元数据

要修改元数据:

>>> t.meta['key'] = 'value'

选择或重新排序列

可以创建包含列子集或重新排序的列列表的新表,如下例所示:

>>> t = Table(arr, names=('a', 'b', 'c'))
>>> t_acb = t['a', 'c', 'b']

另一种方法是提供一个列表或元组作为项,如下所示:

>>> new_order = ['a', 'c', 'b']  # List or tuple
>>> t_acb = t[new_order]

告诫#

修改表数据和属性是相当明确的,但是要记住的一点是添加一行 may 在表数据的内存中需要一个新副本。这取决于Python对象在内存中的详细布局,无法可靠地控制。在某些情况下,可以在不到O(N**2)的时间内逐行构建一个表,但不能指望它。

另一个要记住的微妙之处是,在某些情况下,操作的返回值会导致内存中的新表,而在其他情况下,它会导致现有表数据的视图。例如,想象一下使用列选择设置两个表元素 t['a', 'c'] 结合行索引选择:

>>> t = Table([[1, 2], [3, 4], [5, 6]], names=('a', 'b', 'c'))
>>> t['a', 'c'][1] = (100, 100)
>>> print(t)
 a   b   c
--- --- ---
  1   3   5
  2   4   6

这可能令人惊讶,因为数据值没有改变,也没有错误。事实上,事情是这样的 t['a', 'c'] 在内存中创建了一个新的临时表作为 copy 然后更新副本的第一行。原来的 t 表不受影响,新的临时表在语句完成后消失。要点是注意如何一步一步地执行某些操作。

就地更新与替换列更新#

考虑以下代码片段:

>>> t = Table([[1, 2, 3]], names=['a'])
>>> t['a'] = [10.5, 20.5, 30.5]

有几种方法可以解决这个问题。它可以就地更新现有的数组值(截断为整数),也可以根据提供的数据值用新列替换整个列。

答案是 astropy 上面显示的操作执行的是 complete replacement 列对象的。在本例中,它通过内部调用创建一个具有浮点值的新列对象 t.replace_column('a', [10.5, 20.5, 30.5]) 。通常情况下,此行为与Python和 pandas 行为。

Forcing in-place update

可以强制对列进行就地更新,如下所示:

t[colname][:] = value

找出问题的根源

为了找到与替换列相关的潜在问题,可以使用以下选项 astropy.table.conf.replace_warnings配置系统 (astropy.config ) 。它控制在某些情况下替换表列时发出的一组警告。此选项必须设置为包含零个或多个以下字符串值的列表:

always

方法每次替换列时都会打印警告 __setitem__() 语法(即, t['a'] = new_col )。

slice

当一列显示为 slice 父列的属性被替换。

refcount

当列的Python引用计数更改时打印警告。这表示存在一个过时的对象,该对象可能会在代码的其他地方使用,并产生意外的结果。

attributes

如果任何标准列属性发生更改,则打印警告。

的默认值 table.conf.replace_warnings 选项是 [] (无警告)。