Table¶
Overview¶
Most methods and functions in Parsons return a Table, which is a 2D list-like object similar to a Pandas Dataframe. You can call the following methods on the Table object to output it into a variety of formats or storage types. A full list of Table methods can be found in the API section.
From Parsons Table¶
Method |
Destination Type |
Description |
|---|---|---|
|
CSV File |
Write a table to a local csv file |
|
Avro File [2] |
Write a table to a local avro file |
|
AWS s3 Bucket |
Write a table to a csv stored in S3 |
|
Google Cloud Storage Bucket |
Write a table to a csv stored in Google Cloud Storage |
|
SFTP Server |
Write a table to a csv stored on an SFTP server |
|
A Redshift Database |
Write a table to a Redshift database |
|
A Postgres Database |
Write a table to a Postgres database |
|
Civis Redshift Database |
Write a table to Civis platform database |
|
Petl |
Convert a |
|
JSON file |
Write a table to a local JSON file |
|
HTML formatted table |
Write a table to a local html file |
|
Pandas Dataframe [1] |
Return a Pandas dataframe |
|
CSV file |
Appends table to an existing CSV |
|
Avro file [2] |
Appends table to an existing Avro file |
|
ZIP file |
Writes a table to a CSV in a zip archive |
|
Dicts |
Write a table as a list of dicts |
To Parsons Table¶
Create Parsons Table object using the following methods.
Method |
Source Type |
Description |
|---|---|---|
|
File like object, local path, url, ftp. |
Loads a csv object into a Table |
|
Avro File [2] |
Load a table from a local avro file |
|
File like object, local path, url, ftp. |
Loads a json object into a Table |
|
List object |
Loads lists organized as columns in Table |
|
Redshift table |
Loads a Redshift query into a Table |
|
Postgres table |
Loads a Postgres query into a Table |
|
Pandas Dataframe [1] |
Load a Parsons table from a Pandas Dataframe |
|
S3 CSV |
Load a Parsons table from a csv file on S3 |
|
File like object, local path, url, ftp. |
Load a CSV string into a Table |
You can also use the Table constructor to create a Table from a list or petl.util.base.Table.
tbl = Table([{'a': 1, 'b': 2}, {'a': 3, 'b': 4}])
tbl = Table([['a', 'b'], [1, 2], [3, 4]])
tbl = Table(petl_tbl)
Parsons Table Attributes¶
Tables have a number of convenience attributes.
Attribute |
Description |
|---|---|
|
The number of rows in the table |
|
A list of column names in the table |
|
The actual data (rows) of the table, as a list of tuples (without field names) |
|
The first value in the table. Use for database queries where a single value is returned. |
Parsons Table Transformations¶
Parsons tables have many methods that allow you to easily transform tables. Below is a selection of commonly used methods. The full list can be found in the API section.
Column Transformations¶
Method |
Description |
|---|---|
|
Get the first n rows of a table |
|
Get the last n rows of a table |
|
Add a column |
|
Remove a column |
|
Rename a column |
|
Rename multiple columns |
|
Move a column within a table |
|
Return a table with a subset of columns |
|
Provide a fixed value to fill a column |
|
Provide a fixed value to fill all null values in a column |
|
Get the python type of values for a given column |
|
Transform the values of a column via arbitrary functions |
|
Coalesce values from one or more source columns |
|
Standardizes column names based on multiple possible values |
Row Transformations¶
Method |
Description |
|---|---|
|
Return a table of a subset of rows based on filters |
|
Stack a number of tables on top of one another |
|
Divide tables into smaller tables based on row count |
|
Removes rows with null values in specified columns |
|
Removes duplicate rows based on optional key(s), and optionally sorts |
Extraction and Reshaping¶
Method |
Description |
|---|---|
|
Unpack dictionary values from one column to top level columns |
|
Unpack list values from one column and add to top level columns |
|
Take a column with nested data and create a new long table |
|
Unpack list or dict values from one column into separate rows |
Parsons Table Indexing¶
To access rows and columns of data within a Parsons table, you can index on them. To access a column
pass in the column name as a string (e.g. tbl['a']) and to access a row, pass in the row index as
an integer (e.g. tbl[1]).
tbl = Table([{'a': 1, 'b': 2}, {'a': 3, 'b': 4}])
tbl['a'] # [1, 3]
tbl = Table([{'a': 1, 'b': 2}, {'a': 3, 'b': 4}])
tbl[1] # {'a': 3, 'b': 4}
A note on indexing and iterating over a table’s data: If you need to iterate over the data, make sure to use the python iterator syntax, so any data transformations can be applied efficiently.
# Some data transformations
table.add_column('newcol', 'some value')
rows_list = [row for row in table]
Warning
If you must index directly into a table’s data, you can do so, but note that data transformations will be applied each time you do so. This code will be very inefficient on a large table.
rows_list = []
for i in range(0, table.num_rows):
rows_list.append(table[i]) # Data transformations will be applied each time through this loop!
PETL¶
The Parsons Table relies heavily on the petl
Python package. You can always access the underlying petl Table, ETL, which will
allow you to perform any petl-supported ETL operations. Additionally, you can use the helper method,
use_petl(), to conveniently perform the same operations on a parsons
Table(). For example:
import petl
tbl = Table()
tbl.table = petl.skipcomments(tbl.table, '#')
or
tbl = Table()
tbl.use_petl('skipcomments', '#', update_table=True)
Lazy Loading¶
The Table makes use of “lazy” loading and “lazy” transformations. What this means is that it tries not to load and process your data until absolutely necessary.
# Specify where to load the data
tbl = Table.from_csv('name_data.csv')
# Specify data transformations
tbl.add_column('full_name', lambda row: row['first_name'] + ' ' + row['last_name'])
tbl.remove_column(['first_name', 'last_name'])
# Save the table elsewhere
# IMPORTANT - The CSV won't actually be loaded and transformed until this step,
# since this is the first time it's actually needed.
tbl.to_redshift('main.name_table')
This “lazy” loading can be very convenient and performant. However, it can make issues hard to debug. Eg. if your data transformations are time-consuming, you won’t actually notice that performance hit until you try to use the data, potentially much later in your code. There may also be cases where it’s possible to get faster execution by caching a table, especially in situations where a single table will be used as the base for several subsequent calculations.
For these cases Parsons provides two utility functions to materialize a Table and all of its transformations.
Method |
Description |
|---|---|
Load all data from the Table into memory and apply any transformations |
|
Load all data from the Table and apply any transformations, then save to a local temp file. |
Quickstart¶
s3 = S3()
csv = s3.get_file('tmc-bucket', 'my_ids.csv')
Table.from_csv(csv).to_civis('TMC','ids.my_ids')
van = VAN(db='MyVoters')
van.activist_codes().to_dataframe()
van = VAN(db='MyVoters')
van.events().to_s3_csv('my-van-bucket','myevents.csv')
API¶
- class parsons.etl.table.Table(lst: list | tuple | Iterator | Table | _EmptyDefault = _EmptyDefault.token, source: str | None = None, name: str | None = None)[source]¶
Create a Parsons Table.
Accepts one of the following: - A list of lists, with list[0] holding field names, and the other lists holding data - A list of dicts - A petl table
- Parameters:
lst (list | tuple | Iterator | petl.util.base.Table | _EmptyDefault) – See above for accepted list formats
source (str | None) – The original data source from which the data was pulled (optional)
name (str | None) – The name of the table (optional)
- property data: Sequence[tuple]¶
Return an iterable object.
This allows iterating over the raw data rows as tuples (without field names).
- property columns: list[str]¶
List the table’s column names.
- Returns:
List of the table’s column names
- property first: Any¶
Return the first value in the table.
Useful for database queries that only return a single value.
If the first value is empty (IndexError), returns
None.
- add_column(column: str, value: Any | None = None, index: int | None = None, if_exists: Literal['fail', 'replace'] = 'fail') Self¶
Add a column to your table.
- Parameters:
column (str) – Name of column to add
value (Any | None) – A fixed or calculated value
index (int | None) – The position of the new column in the table
if_exists (Literal['fail', 'replace']) – If
replace, this function will callfill_column()if the column already exists, rather than raising aValueError.
- Raises:
ValueError – If the column already exists and
if_existsis notreplace- Return type:
- append_avro(target: Path | str, schema: dict | None = None, sample: int = 9, **avro_args) str¶
Append table to an existing Avro file.
In order to use this method, you must have the fastavro library installed. You can install it with pip install parsons[avro].
This method assume that each column has values with the same type for all rows of the source table.
- Parameters:
target (Path | str) – The file path for an existing avro file.
schema (dict | None) – Defines the rows field structure of the file. Check fastavro documentation and Avro schema reference for details.
sample (int) – Defines how many rows are inspectedfor discovering the field types and building a schema for the avro file when the schema argument is not passed.
**avro_args – Additional options to foward directly to fastavro. See fastavro documentation for reference.
- Returns:
The path of the updated file
- Return type:
- append_csv(local_path: Path | str, encoding: str | None = None, errors: str = 'strict', **csvargs) str¶
Append table to an existing CSV.
Additional keyword arguments are passed to
csv.writer(). So, e.g., to override the delimiter from the default CSV dialect, provide the delimiter keyword argument.- Parameters:
local_path (Path | str) – The local path of an existing CSV file. If it ends in
.gz, the file will be compressed.encoding (str | None) – The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
**csvargs – Additional keyword arguments are passed to
csv.writer().
- Returns:
The path of the updated csv file
- Return type:
- chunk(rows: int) list[Table]¶
Divides a Parsons table into smaller tables of a specified row count.
If the table cannot be divided evenly, then the final table will only include the remainder.
- coalesce_columns(dest_column: str, source_columns: Sequence[str], remove_source_columns: bool = True) Self¶
Coalesces values from one or more source columns into a destination column.
The first non-empty value will be used. If the destination column doesn’t exist, it will be added.
- Parameters:
- Return type:
Self
- concat(*tables: Table, missing: Any | None = None) None¶
Concatenates one or more tables onto this one.
Note that the tables do not need to share exactly the same fields. Any missing fields will be padded with
None, or whatever is provided via the missing keyword argument.- Parameters:
tables (Table) – A single table, multiple tables, or a list/tuple of tables.
missing (Any | None) – The value to use when padding missing values
- Return type:
None
- convert_column(column: str | Iterable[str], updater: Callable | str | dict[Any, Any], *args, **kwargs) Self¶
Transform values under one or more fields.
Transformation is possible via arbitrary functions, method invocations or dictionary translations.
This leverages
petl.convert(). Example usage can be found here.- Parameters:
column (str | Iterable[str]) – Column(s) to convert (name, iterable)
updater (Callable | str | dict[Any, Any]) – Update via Callable, method name, dict translation, or variable to process the update
*args – Additional positional arguments to pass to
petl.convert()**kwargs – Additional keyword arguments to pass to
petl.convert()
- Return type:
Self
- convert_columns_to_str() Self¶
Convert all non-string or mixed columns strings.
Can be very useful for comparison operations.
- Return type:
- convert_table(updater: Callable | str | dict[Any, Any], *args, **kwargs) Self¶
Transform all cells in a table.
Useful for cleaning fields and data hygiene functions such as regex.
Transformation is possible via arbitrary functions, method invocations or dictionary translations.
This leverages
petl.convert(). Example usage can be found here.
- deduplicate(keys: str | Sequence[str] | None = None, presorted: bool = False) Self¶
Deduplicate table.
All keys specified in the
keysargument are considered when deduplicating, not each key individually. For example, ifkeys=['a', 'b'], the method will not remove a record unless it’s identical to another record in both columnsaandb.tbl.table¶ a
b
1
3
1
2
1
2
2
3
Remove all subsequent rows with {‘a’: 1}¶tbl = Table([['a', 'b'], [1, 3], [1, 2], [1, 2], [2, 3]]) tbl.deduplicate('a')
tbl.table¶ a
b
1
3
2
3
Remove all subsequent rows with {‘a’: 1} and {‘b’: 3}¶tbl = Table([['a', 'b'], [1, 3], [1, 2], [1, 2], [2, 3]]) tbl.deduplicate(['a', 'b']) # Table is deduplicated on both ('a', 'b'), so as (1, 2) was placed # before (1, 3) second instance of {'a': 1} or {'b': 3} was not removed.
tbl.table¶ a
b
1
2
1
3
2
3
Remove all subsequent rows with {‘a’: 1} and then all with {‘b’: 3}¶tbl = Table([['a', 'b'], [1, 3], [1, 2], [1, 2], [2, 3]]) # reset tbl.deduplicate('a').deduplicate('b')
tbl.table¶ a
b
1
3
The order of deduplication matters¶tbl = Table([['a', 'b'], [1, 3], [1, 2], [1, 2], [2, 3]]) # reset tbl.deduplicate('b').deduplicate('a')
tbl.table¶ a
b
1
2
- fillna_column(column_name: str, fill_value: Any) Self¶
Fill only
Nonevalues of a column in a table.
- classmethod from_avro(local_path: Path | str, limit: int | None = None, skips: int | None = 0, **avro_args) Table¶
Create a Table from an Avro file.
- classmethod from_bigquery(sql: str, app_creds: str | None = None, project: str | None = None, sql_parameters: list | dict | None = None) Table | None¶
Create a Table from a BigQuery statement.
To pull an entire BigQuery table, use a query like
SELECT * FROM {{ table }}.- Parameters:
sql (str) – str A valid SQL statement
app_creds (str | None) – str A credentials json string or a path to a json file. Not required if
GOOGLE_APPLICATION_CREDENTIALSenv variable set.project (str | None) – str The project which the client is acting on behalf of. If not passed then will use the default inferred environment.
sql_parameters (list | dict | None) – To include python variables in your query, it is recommended to pass them as parameters. Using the sql_parameters argument ensures that values are escaped properly, and avoids SQL injection attacks.
- Return type:
Table | None
- classmethod from_columns(cols: Sequence[Sequence[str]], header: Sequence[str] | None = None) Table¶
Create a Table from a list of lists organized as columns.
- classmethod from_csv(local_path: Path | str, **csvargs) Table¶
Create a Table from a CSV file.
- Parameters:
local_path (Path | str) – A csv formatted local path, url or ftp. If this is a file path that ends in
.gz, the file will be decompressed first.**csvargs – Additional arguments to pass to
csv.reader()
- Return type:
- classmethod from_csv_string(csv_string: str, *, str: str | None = None, **csvargs) Table¶
Create a Table from a string representing a CSV.
- Parameters:
csv_string (str) – The string object to convert to a table
**csvargs – Additional arguments to pass to
csv.reader()str (str | None) – Deprecated, use csv_string instead
- Return type:
- classmethod from_dataframe(dataframe: DataFrame, include_index: bool = False) Table¶
Create a Table from a Pandas dataframe.
- classmethod from_json(local_path: Path | str, header: Sequence[str] | None = None, line_delimited: bool = False) Table¶
Create a Table from a json file.
- Parameters:
local_path (Path | str) – A JSON formatted local path, url or ftp. If this is a file path that ends in
.gz, the file will be decompressed first.header (Sequence[str] | None) – List of columns to use for the destination table. If omitted, columns will be inferred from the initial data in the file.
line_delimited (bool) – Whether the file is line-delimited JSON (with a row on each line), or a proper JSON file. If
True, local_path must not be a remote file path.
- Return type:
- classmethod from_postgres(sql: str, username: str | None = None, password: str | None = None, host: str | None = None, db: str | None = None, port: int | None = None, sql_parameters: list | None = None) Table | None¶
Create a Table from a Postgres query.
- Parameters:
sql (str) – A valid SQL statement
username (str | None) – Required if env variable
PGUSERnot populatedpassword (str | None) – Required if env variable
PGPASSWORDnot populatedhost (str | None) – Required if env variable
PGHOSTnot populateddb (str | None) – Required if env variable
PGDATABASEnot populatedport (int | None) – Required if env variable
PGPORTnot populated.sql_parameters (list | None) – To include python variables in your query, it is recommended to pass them as parameters, following the psycopg style. Using the sql_parameters argument ensures that values are escaped properly, and avoids SQL injection attacks.
- Return type:
Table | None
- classmethod from_redshift(sql: str, username: str | None = None, password: str | None = None, host: str | None = None, db: str | None = None, port: int | None = None, sql_parameters: list[Any] | dict[str, Any] | None = None) Table | None¶
Create a Table from a Redshift query.
To pull an entire Redshift table, use a query like
SELECT * FROM tablename.- Parameters:
sql (str) – A valid SQL statement
username (str | None) – Required if env variable
REDSHIFT_USERNAMEnot populatedpassword (str | None) – Required if env variable
REDSHIFT_PASSWORDnot populatedhost (str | None) – Required if env variable
REDSHIFT_HOSTnot populateddb (str | None) – Required if env variable
REDSHIFT_DBnot populatedport (int | None) – Required if env variable
REDSHIFT_PORTnot populated. Port 5439 is typical.sql_parameters (list[Any] | dict[str, Any] | None) – To include python variables in your query, it is recommended to pass them as parameters, following the documentation for passing parameters to SQL queries. Using the sql_parameters argument ensures that values are escaped properly, and avoids SQL injection attacks.
- Return type:
Table | None
- classmethod from_s3_csv(bucket: str, key: str, from_manifest: bool = False, aws_access_key_id: str | None = None, aws_secret_access_key: str | None = None, **csvargs) Table¶
Create a Table from a key in an S3 bucket.
- Parameters:
bucket (str) – The S3 bucket.
key (str) – The S3 key
from_manifest (bool) – bool If True, treats key as a manifest file and loads all urls into a Table.
aws_access_key_id (str | None) – Required if not included as environmental variable.
aws_secret_access_key (str | None) – Required if not included as environmental variable.
**csvargs – Additional arguments to pass to
csv.reader()
- Return type:
- get_columns_type_stats() list[ColumnTypes]¶
Return descriptive stats for all columns.
- Returns:
A list of dicts, each containing a column
nameand atypelist.- Return type:
list[ColumnTypes]
- static get_normalized_column_name(column_name: str) str¶
Return a column name with whitespace and non-alphanumeric characters removed, and everything lowercased.
- long_table(key: Sequence[str], column: str, key_rename: dict[str, str] | None = None, retain_original: bool = False, prepend: bool = True, prepend_value: str | None = None) Table¶
Create a new long parsons table from a column, including the foreign key.
# Begin with nested dicts in a column json = [ { 'id': '5421', 'name': 'Jane Green', 'emails': [ {'home': 'jane@gmail.com'}, {'work': 'jane@mywork.com'} ] } ] tbl = Table(json) print (tbl) >>> {'id': '5421', 'name': 'Jane Green', 'emails': [{'home': 'jane@gmail.com'}, {'work': 'jane@mywork.com'}]} >>> {'id': '5421', 'name': 'Jane Green', 'emails': [{'home': 'jane@gmail.com'}, {'work': 'jane@mywork.com'}]} # Create skinny table of just the nested dicts email_skinny = tbl.long_table(['id'], 'emails') print (email_skinny) >>> {'id': '5421', 'emails_home': 'jane@gmail.com', 'emails_work': None} >>> {'id': '5421', 'emails_home': None, 'emails_work': 'jane@mywork.com'}
- Parameters:
key (Sequence[str]) – The columns to retain in the long table (e.g. foreign keys)
column (str) – The column name to make long
key_rename (dict[str, str] | None) – The new name for the foreign key to better identify it. For example, you might want to rename
idtoperson_id. Ex.{'KEY_NAME': 'NEW_KEY_NAME'}retain_original (bool) – Retain the original column from the source table.
prepend (bool) – Prepend the column name of the unpacked values. Useful for avoiding duplicate column names.
prepend_value (str | None) – Value to prepend new columns if prepend is
True. IfNone, will set to column name.
- Return type:
- map_and_coalesce_columns(column_map: dict[str, Sequence[str]]) Self¶
Coalesce columns based on multiple possible values.
The columns in the map do not need to be in your table, so you can create a map with all possibilities.
The coalesce will occur in the order that the columns are listed, unless the destination column name already exists in the table, in which case that value will be preferenced.
Helpful when your input table might have multiple / unknown column names.
tbl = [ {'first': None}, {'fn': 'Jane'}, {'lastname': 'Doe'}, {'dob': '1980-01-01'} ] column_map = { 'first_name': ['fn', 'first', 'firstname'], 'last_name': ['ln', 'last', 'lastname'], 'date_of_birth': ['dob', 'birthday'] } tbl.map_and_coalesce_columns(column_map) print (tbl) >> {{'first_name': 'Jane', 'last_name': 'Doe', 'date_of_birth': '1908-01-01'}}
- map_columns(column_map: dict[str, Sequence[str]], exact_match: bool = True) Self¶
Standardize column names based on multiple possible values.
Helpful when your input table might have multiple / unknown column names.
tbl = [ {'fn': 'Jane'}, {'lastname': 'Doe'}, {'dob': '1980-01-01'} ] column_map = { 'first_name': ['fn', 'first', 'firstname'], 'last_name': ['ln', 'last', 'lastname'], 'date_of_birth': ['dob', 'birthday'] } tbl.map_columns(column_map) print (tbl) >> {{'first_name': 'Jane', 'last_name': 'Doe', 'date_of_birth': '1908-01-01'}}
- match_columns(desired_columns: Sequence[str], fuzzy_match: bool = True, if_extra_columns: Literal['remove', 'ignore', 'fail'] = 'remove', if_missing_columns: Literal['add', 'ignore', 'fail'] = 'add') Self¶
Change the column names and ordering in this Table to match a list of desired column names.
- Parameters:
desired_columns (Sequence[str]) – Ordered list of desired column names
fuzzy_match (bool) – Whether to normalize column names when matching against the desired column names, removing whitespace and non-alphanumeric characters, and lowercasing everything. Eg. With this flag set,
FIRST NAMEwould matchfirst_name. If the Table has two columns that normalize to the same string (eg.FIRST NAMEandfirst_name), the latter will be considered an extra column.if_extra_columns (Literal['remove', 'ignore', 'fail']) – If the Table has columns that don’t match any desired columns, either
removethem,ignorethem, orfail(raising an error).if_missing_columns (Literal['add', 'ignore', 'fail']) – If the Table is missing some of the desired columns, either
addthem (with a value ofNone),ignorethem, orfail(raising an error).
- Return type:
Self
- reduce_rows(columns: Sequence[str], reduce_func: Callable[[Sequence[str], Sequence[Any]], Sequence[Any]], headers: Sequence[str], presorted: bool = False, **kwargs) Self¶
Group rows by a column or columns, then reduce the groups to a single row.
For example, the output from the query to get a table’s definition is returned as one component per row. The reduce_rows method can be used to reduce all those to a single row containg the entire query.
Based on the rowreduce petl function.
ddl = rs.query(sql_to_get_table_ddl)
ddl.table¶ schemaname
tablename
ddl
‘db_scratch’
‘state_fips’
‘–DROP TABLE db_scratch.state_fips;’
‘db_scratch’
‘state_fips’
‘CREATE TABLE IF NOT EXISTS db_scratch.state_fips’
‘db_scratch’
‘state_fips’
‘(’
‘db_scratch’
‘state_fips’
‘\tstate VARCHAR(1024) ENCODE RAW’
‘db_scratch’
‘state_fips’
‘\t,stusab VARCHAR(1024) ENCODE RAW’
reducer_fn = lambda cols, rows: [ f"{cols[0]}.{cols[1]}", r"\n".join([row[2] for row in rows]) ] ddl.reduce_rows( ['schemaname', 'tablename'], reducer_fn, ['tablename', 'ddl'], presorted=True )
ddl.table¶ tablename
ddl
‘db_scratch.state_fips’
‘–DROP TABLE db_scratch.state_fips;\nCREATE TABLE IF NOT EXISTS db_scratch.state_fips\n(\n\tstate VARCHAR(1024) ENCODE RAW\n\t ,db_scratch.state_fips\n(\n\tstate VARCHAR(1024) ENCODE RAW \n\t,stusab VARCHAR(1024) ENCODE RAW\n\t,state_name VARCHAR(1024) ENCODE RAW\n\t,statens VARCHAR(1024) ENCODE RAW\n)\nDISTSTYLE EVEN\n;’
- Parameters:
columns (Sequence[str]) – The column(s) by which to group the rows.
reduce_func (Callable[[Sequence[str], Sequence[Any]], Sequence[Any]]) – The function by which to reduce the rows. Should take the 2 arguments, the columns list and the rows list and return a list.
reducer(columns: Sequence[str], rows: Sequence[Any]) -> Sequence[Any]:headers (Sequence[str]) – The list of headers for modified table. The length of headers should match the length of the list returned by the reduce function.
presorted (bool) – If false, the row will be sorted.
**kwargs – Extra options to pass to
petl.rowreduce()
- Return type:
Self
- remove_null_rows(columns: str | Sequence[str], null_value: int | float | str | None = None) Self¶
Remove rows if the values in a column are
None.If multiple columns are passed as list, all rows with null values in any of the passed columns will be removed.
- rename_column(column_name: str, new_column_name: str) Self¶
Rename an existing column.
- Parameters:
- Raises:
ValueError – If the new column name already exists
- Return type:
- row_data(row_index: int) dict[str, Any][source]¶
Return a row in table.
Calling this method excessively will log a warning advising of a more efficient alternative.
- select_rows(*filters: Callable | str) Table¶
Select specific rows from a Parsons table based on the passed filters.
Example filters:
The filter can be structured in different ways¶tbl = Table( [ ['foo', 'bar', 'baz'], ['c', 4, 9.3], ['a', 2, 88.2], ['b', 1, 23.3] ] ) # Lambda Function tbl2 = tbl.select_rows(lambda row: row.foo == 'a' and row.baz > 88.1) tbl2 >>> {'foo': 'a', 'bar': 2, 'baz': 88.1} # Expression String tbl3 = tbl.select_rows("{foo} == 'a' and {baz} > 88.1") tbl3 >>> {'foo': 'a', 'bar': 2, 'baz': 88.1}
- set_header(new_header: Sequence[str]) Self¶
Replace the header row of the table.
- Parameters:
new_header (Sequence[str]) – List of new header column names
- Return type:
Self
- sort(columns: Sequence[str] | str | None = None, reverse: bool = False, **kwargs) Self¶
Sort the rows a table.
- stack(*tables: Table, missing: Any | None = None) None¶
Stack Parsons tables on top of one another.
Similar to
concat(), except no attempt is made to align fields from different tables.- Parameters:
tables (Table) – A single table, multiple tables, or a list/tuple of tables.
missing (Any | None) – The value to use when padding missing values
- Return type:
None
- to_avro(target: Path | str, schema: dict | None = None, sample: int = 9, codec: Literal['null', 'deflate', 'bzip2', 'snappy', 'zstandard', 'lz4', 'xz'] = 'deflate', compression_level: int | None = None, **avro_args) str¶
Output table to an Avro file.
In order to use this method, you must have the fastavro library installed. You can install it with pip install parsons[avro].
Write the table into a new avro file according to schema passed.
This method assume that each column has values with the same type for all rows of the source table.
Avro is a data serialization framework that is generally is faster and safer than text formats like Json, XML or CSV.
- Parameters:
target (Path | str) – The file path for creating the avro file. Note that if a file already exists at the given location, it will be overwritten.
schema (dict | None) – Defines the rows field structure of the file. Check fastavro documentation and Avro schema reference for details.
sample (int) – Defines how many rows are inspectedfor discovering the field types and building a schema for the avro file when the schema argument is not passed.
codec (Literal['null', 'deflate', 'bzip2', 'snappy', 'zstandard', 'lz4', 'xz']) – The codec argument (string, optional) sets the compression codec used to shrink data in the file.
compression_level (int | None) – Sets the level of compression to use with the specified codec, if supported.
**avro_args – Additional options to foward directly to fastavro. See fastavro documentation for reference.
- Returns:
The path of the written file
- Return type:
Example usage for writing files¶table2 = [ ['name', 'friends', 'age'], ['Bob', 42, 33], ['Jim', 13, 69], ['Joe', 86, 17], ['Ted', 23, 51]. ] # Define Avro schema schema2 = { 'doc': 'Some people records.', 'name': 'People', 'namespace': 'test', 'type': 'record', 'fields': [ {'name': 'name', 'type': 'string'}, {'name': 'friends', 'type': 'int'}, {'name': 'age', 'type': 'int'}, ], } # Demonstrate writing with Table.toavro() from parsons import Table Table.toavro(table2, 'example.file2.avro', schema=schema2) # Read back with with Table.fromavro() tbl2 = Table.fromavro('example.file2.avro')
tbl2¶ name
friends
age
‘Bob’
42
33
‘Jim’
13
69
‘Joe’
86
17
‘Ted’
23
51
- to_bigquery(table_name: str, app_creds: str | None = None, project: str | None = None, **kwargs) None¶
Write a table to BigQuery.
- Parameters:
table_name (str) – Table name to write to in BigQuery. This should be in
schema.tableformat.app_creds (str | None) – A credentials json string or a path to a json file. Not required if
GOOGLE_APPLICATION_CREDENTIALSenv variable set.project (str | None) – The project which the client is acting on behalf of. If not passed then will use the default inferred environment.
**kwargs – Additional keyword arguments passed to
parsons.google.google_bigquery.GoogleBigQuery.copy(). (if_exists,max_errors, etc.)
- Return type:
None
- to_civis(table: str, api_key: str | None = None, db: str | None = None, max_errors: int | None = None, existing_table_rows: Literal['fail', 'truncate', 'append', 'drop'] = 'fail', diststyle: Literal['even', 'all', 'key'] | None = None, distkey: str | None = None, sortkey1: str | None = None, sortkey2: str | None = None, wait: bool = True, **civisargs) CivisFuture | None¶
Write the table to a Civis Redshift cluster.
Additional keyword arguments can passed to
civis.io.dataframe_to_civis().- Parameters:
table (str) – str The schema and table you want to upload to (e.g.
scratch.table). Schemas or tablenames with periods must be double quoted (e.g.scratch."my.table").api_key (str | None) – Your Civis API key. If not given, the CIVIS_API_KEY environment variable will be used.
db (str | None) – The Civis Database. Can be database name or ID
max_errors (int | None) – The maximum number of rows with errors to remove from the import before failing.
existing_table_rows (Literal['fail', 'truncate', 'append', 'drop']) – The behaviour if a table with the requested name already exists.
diststyle (Literal['even', 'all', 'key'] | None) – The distribution style for the table.
distkey (str | None) – The column to use as the distkey for the table.
sortkey1 (str | None) – The column to use as the sortkey for the table.
sortkey2 (str | None) – The second column in a compound sortkey for the table.
wait (bool) – Wait for write job to complete before exiting method.
- Return type:
CivisFuture | None
- to_csv(local_path: Path | str | None = None, temp_file_compression: Literal['gzip', 'zip'] | None = None, encoding: str | None = None, errors: str = 'strict', write_header: bool = True, csv_name: str | None = None, **csvargs) str¶
Output table to a CSV.
Additional key word arguments are passed to
csv.writer(). So, e.g., to override the delimiter from the default CSV dialect, provide the delimiter keyword argument.Warning
If a file already exists at the given location, it will be overwritten.
- Parameters:
local_path (Path | str | None) – The path to write the csv locally. If it ends in
.gzor.zip, the file will be compressed. If not specified, a temporary file will be created and returned, and that file will be removed automatically when the script is done running.temp_file_compression (Literal['gzip', 'zip'] | None) – If a temp file is requested (ie. no local_path is specified), the compression type for that file. Currently
None,gziporzipare supported. If a local_path is specified, this argument is ignored.encoding (str | None) –
The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
write_header (bool) – Include header in output
csv_name (str | None) – If
zipcompression (either specified or inferred), the name of csv file within the archive.**csvargs – Additional arguments to pass to
csv.writer()
- Returns:
The path of the new file
- Return type:
- to_dataframe(index: str | Sequence[str] | None = None, exclude: Sequence[str] | None = None, columns: Sequence[str] | None = None, coerce_float: bool = False) DataFrame¶
Output Table as a Pandas Dataframe.
In order to use this method, you must have the pandas library installed. You can install it with pip install parsons[pandas].
- Parameters:
index (str | Sequence[str] | None) – Field of array to use as the index, alternately a specific set of input labels to use.
exclude (Sequence[str] | None) – Columns or fields to exclude
columns (Sequence[str] | None) – Column names to use. If the passed data do not have names associated with them, this argument provides names for the columns. Otherwise this argument indicates the order of the columns in the result (any names not found in the data will become all-NA columns).
coerce_float (bool)
- Return type:
DataFrame
- to_gcs_csv(bucket_name: str, blob_name: str, gcs_client: GoogleCloudStorage | None = None, app_creds: str | None = None, project: str | None = None, compression: Literal['zip', 'gzip'] | None = None, encoding: str | None = None, errors: str = 'strict', write_header: bool = True, public_url: bool = False, public_url_expires: int = 60, **csvargs) str | None¶
Write the table to a Google Cloud Storage blob as a CSV.
- Parameters:
bucket_name (str) – The bucket to upload to
blob_name (str) – The blob to name the file. If it ends in
.gzor.zip, the file will be compressed.gcs_client (GoogleCloudStorage | None) – The GCS client to use. If not specified, a default client will be initialized.
app_creds (str | None) – A credentials json string or a path to a json file. Not required if
GOOGLE_APPLICATION_CREDENTIALSenv variable set.project (str | None) – The project which the client is acting on behalf of. If not passed then will use the default inferred environment.
compression (Literal['zip', 'gzip'] | None) – The compression type for the csv. If specified, will override the key suffix.
encoding (str | None) –
The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
write_header (bool) – Include header in output
public_url (bool) – Create a public link to the file
public_url_expire – The time, in minutes, until the url expires if public_url set to
True.**csvargs – Additional arguments to pass to
csv.reader()public_url_expires (int)
- Returns:
If public_url is
True, the public url of the file. OtherwiseNone.- Return type:
str | None
- to_html(local_path: Path | str | None = None, encoding: str | None = None, errors: str | None = 'strict', index_header: bool = False, caption: str | None = None, tr_style: str | Callable | None = None, td_styles: str | Callable | dict[str, str | Callable] | None = None, truncate: int | None = None) str¶
Output table to HTML file.
Warning
If a file already exists at the given location, it will be overwritten.
- Parameters:
local_path (Path | str | None) – The path to write the html locally. If not specified, a temporary file will be created and returned.
encoding (str | None) – The encoding type for csv.writer()
errors (str | None) – Raise an Error if encountered
index_header (bool) – Prepend index to column names; Defaults to False.
caption (str | None) – A caption to include with the html table.
tr_style (str | Callable | None) – Style to be applied to the table row.
td_styles (str | Callable | dict[str, str | Callable] | None) – Styles to be applied to the table cells.
truncate (int | None) – Length of cell data.
- Returns:
The path of the new file
- Return type:
- to_json(local_path: Path | str | None = None, temp_file_compression: Literal['gzip'] | None = None, line_delimited: bool = False) str¶
Output table to a JSON file.
Warning
If a file already exists at the given location, it will be overwritten.
- Parameters:
local_path (Path | str | None) – The path to write the JSON locally. If it ends in
.gz, it will be compressed first. If not specified, a temporary file will be created and returned.temp_file_compression (Literal['gzip'] | None) – If a temp file is requested (ie. no local_path is specified), the compression type for that file. If a local_path is specified, this argument is ignored.
line_delimited (bool) – Whether the file will be line-delimited JSON (with a row on each line), or a proper JSON file.
- Returns:
The path of the new file
- Return type:
- to_petl() Table¶
Provide only the petl table.
- Return type:
Table
- to_postgres(table_name: str, username: str | None = None, password: str | None = None, host: str | None = None, db: str | None = None, port: int | None = None, **copy_args) None¶
Write a table to a Postgres database.
- Parameters:
table_name (str) – The table name and schema (
my_schema.my_table) to point the file.username (str | None) – Required if env variable
PGUSERnot populatedpassword (str | None) – Required if env variable
PGPASSWORDnot populatedhost (str | None) – Required if env variable
PGHOSTnot populateddb (str | None) – Required if env variable
PGDATABASEnot populatedport (int | None) – Required if env variable
PGPORTnot populated.**copy_args – See
copy()for options.
- Return type:
None
- to_redshift(table_name: str, username: str | None = None, password: str | None = None, host: str | None = None, db: str | None = None, port: int | None = None, **copy_args) None¶
Write a table to a Redshift database.
Note, this requires you to pass AWS S3 credentials or store them as environmental variables.
- Parameters:
table_name (str) – The table name and schema (
my_schema.my_table) to point the file.username (str | None) – Required if env variable
REDSHIFT_USERNAMEnot populatedpassword (str | None) – Required if env variable
REDSHIFT_PASSWORDnot populatedhost (str | None) – Required if env variable
REDSHIFT_HOSTnot populateddb (str | None) – Required if env variable
REDSHIFT_DBnot populatedport (int | None) – Required if env variable
REDSHIFT_PORTnot populated. Port 5439 is typical.**copy_args – See
copy()for options.
- Return type:
None
- to_s3_csv(bucket: str, key: str, aws_access_key_id: str | None = None, aws_secret_access_key: str | None = None, compression: Literal['gzip', 'zip'] | None = None, encoding: str | None = None, errors: str = 'strict', write_header: bool = True, acl: str = 'bucket-owner-full-control', public_url: bool = False, public_url_expires: int = 3600, use_env_token: bool = True, **csvargs) str | None¶
Write the table to an s3 object as a CSV.
- Parameters:
bucket (str) – The s3 bucket to upload to
key (str) – The s3 key to name the file. If it ends in
.gzor.zip, the file will be compressed.aws_access_key_id (str | None) – Required if not included as environmental variable
aws_secret_access_key (str | None) – Required if not included as environmental variable
compression (Literal['gzip', 'zip'] | None) – str The compression type for the s3 object. If specified, will override the key suffix.
encoding (str | None) –
The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
write_header (bool) – Include header in output
acl (str) – The S3 permissions on the file
public_url (bool) – Create a public link to the file
public_url_expire – The time, in seconds, until the url expires (if public_url set to
True).use_env_token (bool) – Controls use of the
AWS_SESSION_TOKENenvironment variable for S3. Defaults toTrue. Set toFalsein order to ignore theAWS_SESSION_TOKENenv variable even if the aws_session_token argument was not passed in.**csvargs – Additional arguments to pass to
csv.reader()public_url_expires (int)
- Returns:
If public_url is
True, the public url of the file. OtherwiseNone.- Return type:
str | None
- to_sftp_csv(remote_path: str, host: str, username: str, password: str, port: int = 22, encoding: str | None = None, errors: str = 'strict', write_header: bool = True, rsa_private_key_file: Path | str | None = None, **csvargs) None¶
Write the table to a CSV file on a remote SFTP server.
- Parameters:
remote_path (str) – The remote path of the file. If it ends in
.gz, the file will be compressed.host (str) – The remote host
username (str) – The username to access the SFTP server
password (str) – The password to access the SFTP server
port (int) – The port number of the SFTP server
encoding (str | None) –
The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
write_header (bool) – Include header in output
rsa_private_key_file (Path | str | None) – str Absolute path to a private RSA key used to authenticate SFTP connection
**csvargs – Additional keyword arguments passed to
csv.writer().
- Return type:
None
- to_zip_csv(archive_path: Path | str | None = None, csv_name: str | None = None, encoding: str | None = None, errors: str = 'strict', write_header: bool = True, if_exists: Literal['replace', 'append'] = 'replace', **csvargs) str¶
Output table to a CSV in a zip archive.
Additional key word arguments are passed to
csv.writer(). So, e.g., to override the delimiter from the default CSV dialect, provide the delimiter keyword argument. Use this method if you would like to write multiple csv files to the same archive.Warning
If a file already exists in the archive, it will be overwritten.
- Parameters:
archive_path (Path | str | None) – The path to zip achive. If not specified, a temporary file will be created and returned.
csv_name (str | None) – The name of the csv file to be stored in the archive. If
None, will use the archive name.encoding (str | None) –
The CSV encoding type for csv.writer()
errors (str) – Raise an Error if encountered
write_header (bool) – Include header in output
if_exists (Literal['replace', 'append']) – What to do if archive already exists.
**csvargs – Additional keyword arguments passed to
csv.writer().
- Returns:
The path of the archive
- Return type:
- unpack_dict(column: str, keys: list | None = None, include_original: bool = False, sample_size: int = 5000, missing: str | None = None, prepend: bool = True, prepend_value: str | None = None) Self¶
Unpack dictionary values from one column into separate columns.
- Parameters:
column (str) – The column name to unpack
keys (list | None) – The dict keys in the column to unpack. If
None, will unpack all.include_original (bool) – Whether to retain original column after unpacking
sample_size (int) – Number of rows to sample before determining columns
missing (str | None) – If a value is missing, fill with this value
prepend (bool) – Prepend the column name of the unpacked values. Useful for avoiding duplicate column names.
prepend_value (str | None) – Value to prepend new columns if
prepend=True. IfNone, will set to column name.
- Return type:
- unpack_list(column: str, include_original: bool = False, missing: str | None = None, replace: bool = False, max_columns: int | None = None) Table | None¶
Unpack list values from one column into separate, numbered columns.
# Begin with a list in column json = [{ 'id': '5421', 'name': 'Jane Green', 'phones': ['512-699-3334', '512-222-5478'] }] tbl = Table(json) print (tbl) >>> {'id': '5421', 'name': 'Jane Green', 'phones': ['512-699-3334', '512-222-5478']} tbl.unpack_list('phones', replace=True) print (tbl) >>> {'id': '5421', 'name': 'Jane Green', 'phones_0': '512-699-3334', 'phones_1': '512-222-5478'}
- Parameters:
column (str) – The column name to unpack
include_original (bool) – Retain original column after unpacking
sample_size – Number of rows to sample before determining columns
missing (str | None) – If a value is missing, fill it with this value
replace (bool) – Return new table or update existing
max_columns (int | None) – The maximum number of columns to unpack
- Return type:
Table | None
- unpack_nested_columns_as_rows(column: str, key: str = 'id', expand_original: bool | int = False) Table¶
Unpack list or dict values from one column into separate rows.
Not recommended for JSON columns (i.e. lists of dicts), but can handle columns with any mix of types. Makes use of
petl.melt().- Parameters:
column (str) – The column name to unpack
key (str) – The column to use as a key when unpacking. Defaults to
id.expand_original (bool | int) – If int: Add to original unless the max added per key is above the given number If
True: Add resulting unpacked rows (with all other columns) to original IfFalse(default): Return unpacked rows (with key column only) as standalone In all cases, packed list and dict rows are removed from the original.
- Returns:
If expand_original is not
False, original table with packed rows replaced by unpacked rows. Otherwise, standalone table with key column and unpacked values only- Return type:
- use_petl(petl_method: str, *args, **kwargs) Table¶
Call a petl function on the current table.
This convenience method exposes the petl functions to the current Table. This is useful in cases where one might need a
petlfunction that has not yet been implemented for Table.For more information on available petl functions, see the transform and util documentation.
tbl = Table( [ ['col1', 'col2'], ['# this is a comment row'], ['a', 1], ['#this is another comment', 'this is also ignored'], ['b', 2] ] ) tbl.use_petl('skipcomments', '#', update_table=True) >>> {'col1': 'a', 'col2': 1} >>> {'col1': 'b', 'col2': 2}
tbl.table¶ col1
col2
‘a’
1
‘b’
2
- Parameters:
petl_method (str) – The name of the
petlfunction to call*args – Any The arguements to pass to the petl function.
**kwargs – Any The keyword arguements to pass to the petl function. update_table (bool) – If
True, updates the Table. Defaults toFalse. to_petl (bool) – IfTrue, returns a petl table, otherwise a Table. Defaults toFalse.
- Return type:
- column_data(column_name: str) list[source]¶
Return the data in the column as a list.
- Parameters:
column_name (str) – The name of the column
- Returns:
All data in the column
- Raises:
ValueError – If the column name is not found.
- Return type:
- materialize() None[source]¶
“Materialize” a Table.
All data is loaded into memory and all pending transformations are applied.
Use this if petl’s lazy-loading behavior is causing you problems, eg. if you want to read data from a file immediately.
This method updates the current table in place.
- Return type:
None
- materialize_to_file(file_path: Path | str | None = None) str[source]¶
“Materialize” a Table directly to a file.
Unlike the
Table.materialize()method, this loads the data into a local temp file without bringing it into memory.This method updates the current table in place.
- class parsons.etl.table._EmptyDefault(*values)[source]¶
Default, non-mutable argument for Table().
This is used because Table(None) should not be allowed, but we need a default argument that isn’t the mutable [].
See https://stackoverflow.com/a/76606310 for discussion.