0
# Tables
1
2
Flexible table data structure with metadata support, advanced I/O capabilities, table operations (join, stack, group), and integration with units and coordinates.
3
4
## Capabilities
5
6
### Table Creation and Basic Operations
7
8
Create and manipulate heterogeneous data tables with column metadata, units, and astronomical data types.
9
10
```python { .api }
11
class Table:
12
"""
13
Heterogeneous table of data with metadata support.
14
15
Parameters:
16
- data: input data (dict, list, array, etc.)
17
- masked: whether to use masked arrays
18
- names: column names
19
- meta: table metadata dictionary
20
- copy: whether to copy input data
21
- rows: input data as rows instead of columns
22
- copy_indices: whether to copy indices
23
"""
24
def __init__(self, data=None, masked=None, names=None, meta=None,
25
copy=True, rows=None, copy_indices=True, **kwargs): ...
26
27
@classmethod
28
def read(cls, *args, **kwargs):
29
"""
30
Read table from file.
31
32
Supports formats: ASCII, FITS, VOTable, HDF5, CSV, etc.
33
34
Parameters:
35
- filename: file to read
36
- format: file format (auto-detected if not specified)
37
- **kwargs: format-specific options
38
39
Returns:
40
Table: loaded table
41
"""
42
43
def write(self, *args, **kwargs):
44
"""
45
Write table to file.
46
47
Parameters:
48
- filename: output filename
49
- format: output format
50
- **kwargs: format-specific options
51
"""
52
53
def copy(self, copy_data=True):
54
"""Create a copy of the table."""
55
56
def __getitem__(self, item):
57
"""Get column(s) or row(s) from table."""
58
59
def __setitem__(self, item, value):
60
"""Set column or row values."""
61
62
def __len__(self):
63
"""Number of rows in table."""
64
65
@property
66
def colnames(self):
67
"""List of column names."""
68
69
@property
70
def meta(self):
71
"""Table metadata dictionary."""
72
73
def add_column(self, col, index=None, name=None, rename_duplicate=False):
74
"""Add a column to the table."""
75
76
def add_columns(self, cols, indexes=None, names=None, copy=True):
77
"""Add multiple columns to the table."""
78
79
def remove_column(self, name):
80
"""Remove a column from the table."""
81
82
def remove_columns(self, names):
83
"""Remove multiple columns from the table."""
84
85
def rename_column(self, name, new_name):
86
"""Rename a column."""
87
88
def add_row(self, vals=None, mask=None):
89
"""Add a row to the table."""
90
91
def insert_row(self, index, vals=None, mask=None):
92
"""Insert a row at the specified index."""
93
94
def remove_row(self, index):
95
"""Remove a row from the table."""
96
97
def remove_rows(self, row_specifier):
98
"""Remove multiple rows from the table."""
99
100
class QTable(Table):
101
"""
102
Table subclass with enhanced Quantity support.
103
104
Automatically handles unit conversions and quantity operations.
105
"""
106
def __init__(self, *args, **kwargs): ...
107
```
108
109
### Column Operations and Properties
110
111
Individual column management with metadata, units, and data type support.
112
113
```python { .api }
114
class Column:
115
"""
116
Table column with metadata and unit support.
117
118
Parameters:
119
- data: column data
120
- name: column name
121
- unit: physical unit
122
- description: column description
123
- meta: column metadata dictionary
124
- mask: mask for missing values
125
"""
126
def __init__(self, data=None, name=None, unit=None, description=None,
127
meta=None, mask=None, **kwargs): ...
128
129
@property
130
def name(self):
131
"""Column name."""
132
133
@property
134
def unit(self):
135
"""Column unit."""
136
137
@property
138
def description(self):
139
"""Column description."""
140
141
@property
142
def meta(self):
143
"""Column metadata."""
144
145
@property
146
def dtype(self):
147
"""Column data type."""
148
149
def to(self, unit):
150
"""Convert column to different unit."""
151
152
def copy(self, data=None, copy_data=True):
153
"""Create a copy of the column."""
154
155
class MaskedColumn(Column):
156
"""Column supporting masked arrays for missing data."""
157
def __init__(self, *args, **kwargs): ...
158
159
@property
160
def mask(self):
161
"""Boolean mask for missing values."""
162
163
@property
164
def filled_data(self):
165
"""Data with masked values filled."""
166
167
class Row:
168
"""
169
Single row from a table.
170
171
Provides dict-like access to column values in a row.
172
"""
173
def __init__(self, table, index): ...
174
175
def __getitem__(self, item):
176
"""Get value for column."""
177
178
def __setitem__(self, item, value):
179
"""Set value for column."""
180
181
def keys(self):
182
"""Column names in the row."""
183
184
def values(self):
185
"""Values in the row."""
186
```
187
188
### Table Operations and Manipulation
189
190
Advanced table operations including joining, stacking, grouping, and sorting.
191
192
```python { .api }
193
def join(left, right, keys=None, join_type='inner', uniq_col_name='{col_name}_{table_name}',
194
table_names=['1', '2'], metadata_conflicts='warn'):
195
"""
196
Join two tables on matching column values.
197
198
Parameters:
199
- left, right: tables to join
200
- keys: column names to join on
201
- join_type: 'inner', 'outer', 'left', 'right', 'cartesian'
202
- uniq_col_name: format for non-unique column names
203
- table_names: names for tables in case of conflicts
204
- metadata_conflicts: how to handle metadata conflicts
205
206
Returns:
207
Table: joined table
208
"""
209
210
def vstack(tables, join_type='outer', metadata_conflicts='warn'):
211
"""
212
Vertically stack tables (concatenate rows).
213
214
Parameters:
215
- tables: list of tables to stack
216
- join_type: how to handle column differences
217
- metadata_conflicts: metadata conflict resolution
218
219
Returns:
220
Table: stacked table
221
"""
222
223
def hstack(tables, uniq_col_name='{col_name}_{table_name}', table_names=None):
224
"""
225
Horizontally stack tables (concatenate columns).
226
227
Parameters:
228
- tables: list of tables to stack
229
- uniq_col_name: format for duplicate column names
230
- table_names: names for identifying tables
231
232
Returns:
233
Table: horizontally stacked table
234
"""
235
236
def dstack(tables):
237
"""
238
Stack tables along a new dimension.
239
240
Parameters:
241
- tables: list of tables to stack
242
243
Returns:
244
Table: table with additional dimension
245
"""
246
247
def unique(input_table, keys=None, silent=False):
248
"""
249
Find unique rows in table.
250
251
Parameters:
252
- input_table: input table
253
- keys: columns to consider for uniqueness
254
- silent: suppress warnings
255
256
Returns:
257
Table: table with unique rows
258
"""
259
260
def setdiff(table1, table2, keys=None):
261
"""
262
Set difference between two tables.
263
264
Returns:
265
Table: rows in table1 but not in table2
266
"""
267
```
268
269
### Table Grouping and Aggregation
270
271
Group tables by column values and perform aggregation operations.
272
273
```python { .api }
274
class TableGroups:
275
"""
276
Container for grouped table operations.
277
278
Created by Table.group_by() method.
279
"""
280
def __init__(self, parent_table, indices=None, keys=None): ...
281
282
def aggregate(self, func):
283
"""
284
Aggregate groups using function.
285
286
Parameters:
287
- func: aggregation function or dict of column -> function
288
289
Returns:
290
Table: aggregated results
291
"""
292
293
@property
294
def groups(self):
295
"""List of group tables."""
296
297
@property
298
def keys(self):
299
"""Group key values."""
300
301
def __iter__(self):
302
"""Iterate over groups."""
303
304
def __getitem__(self, item):
305
"""Get specific group."""
306
307
# Table grouping method
308
def group_by(self, keys):
309
"""
310
Group table by column values.
311
312
Parameters:
313
- keys: column name(s) to group by
314
315
Returns:
316
TableGroups: grouped table container
317
"""
318
# This method is added to Table class
319
Table.group_by = group_by
320
```
321
322
### Coordinate and Sky Coordinate Integration
323
324
Special support for astronomical coordinates and sky coordinate columns.
325
326
```python { .api }
327
def join_skycoord(distance_threshold=None):
328
"""
329
Join tables based on sky coordinate proximity.
330
331
Parameters:
332
- distance_threshold: maximum separation for matches
333
334
Returns:
335
function: join function for coordinate-based matching
336
"""
337
338
# SkyCoord column support in tables
339
# SkyCoord objects can be stored directly as table columns
340
from astropy.coordinates import SkyCoord
341
import astropy.units as u
342
343
# Create table with coordinate column
344
ra = [10.1, 20.2, 30.3] * u.degree
345
dec = [40.1, 50.2, 60.3] * u.degree
346
coords = SkyCoord(ra=ra, dec=dec)
347
348
table = Table()
349
table['name'] = ['star1', 'star2', 'star3']
350
table['coords'] = coords
351
table['magnitude'] = [12.1, 13.2, 14.3]
352
```
353
354
### Table I/O and Format Support
355
356
Comprehensive I/O support for astronomical and scientific data formats.
357
358
```python { .api }
359
# Supported formats for Table.read() and Table.write():
360
361
# ASCII formats:
362
# - 'ascii' - basic ASCII
363
# - 'ascii.fixed_width' - fixed width columns
364
# - 'ascii.csv' - comma-separated values
365
# - 'ascii.tab' - tab-separated values
366
# - 'ascii.latex' - LaTeX table format
367
# - 'ascii.html' - HTML table format
368
# - 'ascii.rst' - reStructuredText format
369
# - 'ascii.daophot' - DAOPHOT format
370
# - 'ascii.sextractor' - SExtractor catalog format
371
# - 'ascii.cds' - CDS format
372
# - 'ascii.mrt' - Machine Readable Table format
373
374
# Binary formats:
375
# - 'fits' - FITS binary tables
376
# - 'votable' - VOTable format
377
# - 'hdf5' - HDF5 format
378
# - 'parquet' - Apache Parquet format
379
380
# Registry system for custom formats
381
from astropy.table import registry
382
383
def custom_reader(filename, **kwargs):
384
"""Custom table reader function."""
385
# Implementation
386
pass
387
388
def custom_writer(table, filename, **kwargs):
389
"""Custom table writer function."""
390
# Implementation
391
pass
392
393
registry.register_reader('custom', Table, custom_reader)
394
registry.register_writer('custom', Table, custom_writer)
395
```
396
397
### Table Formatting and Display
398
399
Control table display, formatting, and pretty-printing options.
400
401
```python { .api }
402
class TableFormatter:
403
"""Control table display formatting."""
404
405
def __init__(self, table): ...
406
407
@property
408
def max_lines(self):
409
"""Maximum lines to display."""
410
411
@property
412
def max_width(self):
413
"""Maximum width for display."""
414
415
# Table display configuration (accessed via table.pformat(), table.pprint())
416
def pformat(self, max_lines=None, max_width=None, show_name=True,
417
show_unit=None, show_dtype=False, align=None):
418
"""
419
Format table as string.
420
421
Parameters:
422
- max_lines: maximum lines to show
423
- max_width: maximum width
424
- show_name: show column names
425
- show_unit: show column units
426
- show_dtype: show column data types
427
- align: column alignment
428
429
Returns:
430
str: formatted table string
431
"""
432
433
def pprint(self, *args, **kwargs):
434
"""Pretty-print table to console."""
435
436
# Add these methods to Table class
437
Table.pformat = pformat
438
Table.pprint = pprint
439
```
440
441
## Usage Examples
442
443
### Basic Table Creation and Manipulation
444
445
```python
446
from astropy.table import Table, Column
447
import astropy.units as u
448
import numpy as np
449
450
# Create table from dictionary
451
data = {
452
'name': ['Sirius', 'Canopus', 'Rigel'],
453
'ra': [101.3, 95.5, 78.6] * u.degree,
454
'dec': [-16.7, -52.7, -8.2] * u.degree,
455
'magnitude': [1.46, 0.74, 0.13],
456
'distance': [8.6, 310, 860] * u.lightyear
457
}
458
stars = Table(data)
459
460
print(stars)
461
print(f"Number of stars: {len(stars)}")
462
print(f"Column names: {stars.colnames}")
463
```
464
465
### Table Operations and Joining
466
467
```python
468
# Create two related tables
469
catalog1 = Table({
470
'id': [1, 2, 3],
471
'name': ['Star A', 'Star B', 'Star C'],
472
'magnitude': [12.1, 13.2, 14.3]
473
})
474
475
catalog2 = Table({
476
'id': [1, 2, 4],
477
'parallax': [0.1, 0.05, 0.02] * u.arcsec,
478
'proper_motion': [10, 5, 2] * u.mas/u.year
479
})
480
481
# Join tables on 'id' column
482
combined = join(catalog1, catalog2, keys='id', join_type='inner')
483
print(combined)
484
485
# Stack tables vertically
486
more_stars = Table({
487
'id': [5, 6],
488
'name': ['Star D', 'Star E'],
489
'magnitude': [15.1, 16.2]
490
})
491
all_stars = vstack([catalog1, more_stars])
492
```
493
494
### Working with Units and Quantities
495
496
```python
497
from astropy.table import QTable
498
499
# QTable provides better Quantity support
500
qtable = QTable()
501
qtable['name'] = ['Vega', 'Altair', 'Deneb']
502
qtable['flux'] = [1000, 500, 200] * u.Jy
503
qtable['wavelength'] = [550, 600, 650] * u.nm
504
505
# Unit conversions
506
qtable['flux_cgs'] = qtable['flux'].to(u.erg / u.s / u.cm**2 / u.Hz)
507
qtable['freq'] = qtable['wavelength'].to(u.Hz, equivalencies=u.spectral())
508
509
print(qtable['flux', 'flux_cgs', 'freq'])
510
```
511
512
### Coordinate Integration
513
514
```python
515
from astropy.coordinates import SkyCoord
516
517
# Table with coordinate columns
518
coord_table = Table()
519
coord_table['source'] = ['NGC1234', 'M31', 'M87']
520
521
# Add SkyCoord column directly
522
ra = [123.4, 10.7, 187.7] * u.degree
523
dec = [56.7, 41.3, 12.4] * u.degree
524
coord_table['coords'] = SkyCoord(ra=ra, dec=dec)
525
526
# Add individual coordinate columns
527
coord_table['ra'] = coord_table['coords'].ra
528
coord_table['dec'] = coord_table['coords'].dec
529
coord_table['l'] = coord_table['coords'].galactic.l
530
coord_table['b'] = coord_table['coords'].galactic.b
531
532
print(coord_table)
533
```
534
535
### Grouping and Aggregation
536
537
```python
538
# Table with multiple observations per object
539
observations = Table({
540
'object': ['Star1', 'Star1', 'Star2', 'Star2', 'Star3'],
541
'filter': ['B', 'V', 'B', 'V', 'B'],
542
'magnitude': [12.1, 11.8, 13.2, 12.9, 14.1],
543
'error': [0.1, 0.1, 0.15, 0.12, 0.2]
544
})
545
546
# Group by object
547
grouped = observations.group_by('object')
548
549
# Aggregate - calculate mean magnitude per object
550
mean_mags = grouped.aggregate(np.mean)
551
print(mean_mags)
552
553
# Custom aggregation
554
def weighted_mean(group):
555
weights = 1 / group['error']**2
556
return np.average(group['magnitude'], weights=weights)
557
558
weighted_mags = grouped.aggregate({'magnitude': weighted_mean})
559
```
560
561
### File I/O Operations
562
563
```python
564
# Write table to various formats
565
stars.write('catalog.fits', format='fits')
566
stars.write('catalog.csv', format='ascii.csv')
567
stars.write('catalog.votable', format='votable')
568
569
# Read tables
570
fits_table = Table.read('catalog.fits')
571
csv_table = Table.read('catalog.csv', format='ascii.csv')
572
573
# Format-specific options
574
stars.write('formatted.txt', format='ascii.fixed_width',
575
delimiter=' ', bookend=False)
576
577
# Read with custom options
578
custom_table = Table.read('data.txt', format='ascii',
579
names=['col1', 'col2', 'col3'],
580
data_start=3)
581
```
582
583
### Advanced Table Formatting
584
585
```python
586
# Control display options
587
stars.pprint(max_lines=10, max_width=80, show_unit=True)
588
589
# Custom formatting for specific columns
590
stars['ra'].format = '%.3f'
591
stars['dec'].format = '%.3f'
592
stars['magnitude'].format = '%.2f'
593
594
# Export formatted table
595
formatted_output = stars.pformat(show_name=True, show_unit=True, align=['<', '>', '^'])
596
print(formatted_output)
597
```