call_report.fca.convert_wide_format_to_long_format#
- call_report.fca.convert_wide_format_to_long_format(*, wide: NativeDataFrame, dataframe_type: None = None) NativeDataFrame[source]#
- call_report.fca.convert_wide_format_to_long_format(*, wide: NativeDataFrame, dataframe_type: Literal['pandas']) pandas.DataFrame
- call_report.fca.convert_wide_format_to_long_format(*, wide: NativeDataFrame, dataframe_type: Literal['pyarrow_table']) pyarrow.Table
- call_report.fca.convert_wide_format_to_long_format(*, wide: NativeDataFrame, dataframe_type: Literal['polars_dataframe']) polars.DataFrame
- call_report.fca.convert_wide_format_to_long_format(*, wide: NativeDataFrame, dataframe_type: Literal['polars_lazyframe']) polars.LazyFrame
Convert an already-built wide-format frame to long format.
This function is self-contained. wide’s own column names fully describe the long-format row each one unpivots to (see _parse_wide_column_key), so it needs no FCACallReport instance, layout lookups, or other external metadata.
Column names are schema rather than data. A wide frame has at most a few thousand columns, known statically via collect_schema, so they are parsed in plain Python rather than with narwhals string expressions. That is necessary, not merely stylistic: narwhals.Expr.str.split requires a pyarrow-backed pandas series and raises
TypeErroron plain numpy-backed pandas, this package’s default backend, and Expr.str has no regex-capture-group equivalent to work around it. The reshape itself, one unpivot plus a join against a small lookup frame built from the parsed column names, uses only lazy-safe narwhals operations, so it stays a deferred, uncollected query when wide is a polars.LazyFrame. No duplicate-grain check is needed either, since each wide column maps to exactly one (schedule, code_column, code_value, variable_name) tuple by construction, making the long-format grain unique automatically.Columns are always returned in the order
UNINUM,period,schedule,code_column,code_value,variable_name,value,is_multiple. That order is part of the contract, so a positional read of this frame matches one built by the other route.Every row with a non-null value matches what FCACallReport.to_long_format would build directly from the same source data, but row counts can still differ. Pivoting fills in every (UNINUM, period) by wide-column combination as an explicit null row, including combinations no institution actually reported, such as an investment code one institution used and another never did. to_long_format only ever has a row for a combination that genuinely appeared in the source. Filter to non-null value before comparing row-for-row against a directly-built long-format frame.
- Parameters:
- wideNativeDataFrame
A wide-format frame, e.g. from FCACallReport.to_wide_format.
- dataframe_type{“pandas”, “pyarrow_table”, “polars_lazyframe”, “polars_dataframe”}, optional
The dataframe type to convert the result to as a final step. Leave this
None(the default) to get back whatever backend call_report.config.get_config currently has configured.
- Returns:
- NativeDataFrame
The long-format frame (see FCACallReport.to_long_format for the schema), of the configured backend, or of dataframe_type if it was supplied.
- Raises:
- ReshapeError
If a column name in wide (other than RESHAPE_INDEX) matches neither the plain nor the coded wide-format naming convention.
Examples
>>> from call_report.fca.transport import PackagedArchiveTransport >>> from call_report.fca.report import FCACallReport >>> report = FCACallReport( ... start="2026-03-31", ... end="2026-03-31", ... transport=PackagedArchiveTransport(), ... ) >>> wide = report.to_wide_format(schedules=["RC", "RCB"]) >>> long = convert_wide_format_to_long_format(wide=wide) >>> list(long.columns) ['UNINUM', 'period', 'schedule', 'code_column', 'code_value', 'variable_name', 'value', 'is_multiple']