表索引¶
曾经一次 Table
已创建,则可以在表的一个或多个列上创建索引。索引根据索引列对表中的行进行内部排序,允许按列值检索元素,并提高某些表操作的性能。
创建索引¶
要在表上创建索引,请使用 add_index()
方法:
>>> from astropy.table import Table
>>> t = Table([(2, 3, 2, 1), (8, 7, 6, 5)], names=('a', 'b'))
>>> t.add_index('a')
可选参数 unique
可以指定以创建具有唯一值元素的索引。
若要在多个列上创建复合索引,请传递列列表::
>>> t.add_index(['a', 'b'])
特别是使用 add_index()
方法被视为默认索引或“主键” indices
属性:
>>> t.indices['a']
a rows
--- ----
1 3
2 0
2 2
3 1
>>> t.indices['a', 'b']
a b rows
--- --- ----
1 5 3
2 6 2
2 8 0
3 7 1
使用索引的行检索¶
可以使用两个表属性完成行检索: loc
和 iloc
. 这个 loc
属性可以按列值、列值的范围编制索引( 包括 边界),或列值的列表或nArray::
>>> t = Table([(1, 2, 3, 4), (10, 1, 9, 9)], names=('a', 'b'), dtype=['i8', 'i8'])
>>> t.add_index('a')
>>> t.loc[2]
<Row index=1>
a b
int64 int64
----- -----
2 1
>>> t.loc[[1, 4]]
<Table length=2>
a b
int64 int64
----- -----
1 10
4 9
>>> t.loc[1:3]
<Table length=3>
a b
int64 int64
----- -----
1 10
2 1
3 9
>>> t.loc[:]
<Table length=4>
a b
int64 int64
----- -----
1 10
2 1
3 9
4 9
请注意,默认情况下, loc
使用主索引,这里是列“a”。要使用其他索引,请在检索数据之前传递索引列名:
>>> t.add_index('b')
>>> t.loc['b', 8:10]
<Table length=3>
a b
int64 int64
----- -----
3 9
4 9
1 10
财产 iloc
工作原理类似,只是检索信息必须是整数或切片,并且与索引的排序顺序有关,而不是与列值有关。例如::
>>> t.iloc[0] # smallest row by value 'a'
<Row index=0>
a b
int64 int64
----- -----
1 10
>>> t.iloc['b', 1:] # all but smallest value of 'b'
<Table length=3>
a b
int64 int64
----- -----
3 9
4 9
1 10
对性能的影响¶
当存在索引时,表操作会发生一些变化,在决定使用索引是否会提高性能时,需要考虑许多因素。一般来说,索引具有以下优点:
基于索引列的表分组和排序都变得更快。
按索引检索值比自定义搜索快。
但也有一些注意事项:
创建索引需要时间和内存。
由于自动索引更新,表修改变得更慢。
由于索引重新标记,对表进行切片会变得更慢。
见 here 对于IPython笔记本,可以分析表索引的各个方面。
索引模式¶
这个 index_mode()
方法允许用户通过上下文管理器进入特定的索引模式,从而使表索引行为具有一定的灵活性。目前有三种索引模式: freeze
, copy_on_getitem
和 discard_on_copy
.
这个 freeze
模式防止在修改索引的列时自动更新索引,并且所有索引在上下文结束后自动刷新:
>>> with t.index_mode('freeze'):
... t['a'][0] = 0
... print(t.indices['a']) # unmodified
a rows
--- ----
1 0
2 1
3 2
4 3
>>> print(t.indices['a']) # modified
a rows
--- ----
0 0
2 1
3 2
4 3
这个 copy_on_getitem
模式强制列在切片时复制和重新标记其索引。如果没有此模式,表切片将保留索引,而列切片将不会:
>>> ca = t['a'][[1, 3]]
>>> ca.info.indices
[]
>>> with t.index_mode('copy_on_getitem'):
... ca = t['a'][[1, 3]]
... print(ca.info.indices)
[ a rows
--- ----
2 0
4 1]
这个 discard_on_copy
模式防止在复制列或表时复制索引:
>>> t2 = Table(t)
>>> t2.indices['a']
a rows
--- ----
0 0
2 1
3 2
4 3
>>> t2.indices['b']
b rows
--- ----
1 1
9 2
9 3
10 0
>>> with t.index_mode('discard_on_copy'):
... t2 = Table(t)
... print(t2.indices)
[]
使用索引更新行¶
行更新可以通过分配table属性来完成 loc
完整行或行列表:
>>> t = Table([('w', 'x', 'y', 'z'), (10, 1, 9, 9)], names=('a', 'b'), dtype=['str', 'i8'])
>>> t.add_index('a')
>>> t.loc['x']
<Row index=1>
a b
str1 int64
---- -----
x 1
>>> t.loc['x'] = ['a', 12]
>>> t
<Table length=4>
a b
str1 int64
---- -----
w 10
a 12
y 9
z 9
>>> t.loc[['w', 'y']]
<Table length=2>
a b
str1 int64
---- -----
w 10
y 9
>>> t.loc[['w', 'z']] = [['b',23], ['c',56]]
>>> t
<Table length=4>
a b
str1 int64
---- -----
b 23
a 12
y 9
c 56
使用索引检索行的位置¶
可以使用表属性完成行位置的检索: loc_indices
. 这个 loc_indices
属性可以按列值、列值的范围编制索引( 包括 边界),或列值的列表或nArray::
>>> t = Table([('w', 'x', 'y', 'z'), (10, 1, 9, 9)], names=('a', 'b'), dtype=['str', 'i8'])
>>> t.add_index('a')
>>> t.loc_indices['x']
1
发动机¶
通过创建索引时 add_index()
,关键字参数 engine
可以指定为使用特定的索引引擎。可用的发动机有:
SortedArray
,一个使用底层sorted的排序数组引擎Table
.SCEngine
, a sorted list engine using the Sorted Containers 包裹。BST
,一个基于Python的二进制搜索树引擎。
风景取决于 sortedcontainers
附属国。最重要的是 SortedArray
(默认引擎)通常是最好的 SCEngine
可能更适合于在空列上创建的索引,因为添加新值更快。