Skip to content

excel

excel

Excel

Thin wrapper around a pandas dataframe loaded from (or destined for) an .xlsx file, used throughout build for both input dictionaries and the output spreadsheet.

Source code in source/src/imarina_load_researchers/core/excel.py
class Excel:
    """Thin wrapper around a pandas dataframe loaded from (or destined for)
    an `.xlsx` file, used throughout `build` for both input dictionaries and
    the output spreadsheet."""

    def __init__(
        self,
        path: Path | None,
        skiprows: int = 0,
        header: int | None = 0,
    ) -> None:
        """
        Loads an Excel file into a dataframe, or starts with an empty one.

        Args:
            path (Path | None): Path to the `.xlsx` file to load, or `None`
                to start with an empty dataframe (used by `__copy__`).
            skiprows (int): Number of leading rows to skip before the header,
                forwarded to `pandas.read_excel`.
            header (int | None): Row index to use as the column header,
                forwarded to `pandas.read_excel`.
        """
        if path is None:
            self.dataframe = pd.DataFrame()
        else:
            self.dataframe = pd.read_excel(path, skiprows=skiprows, header=header)

    def parse_two_columns(
        self,
        key: int,
        value: int,
        func_apply_key: Callable[[Any], Any] | None = None,
        func_apply_value: Callable[[Any], Any] | None = None,
    ) -> dict[Any, Any]:
        """
        Builds a `{key: value}` dict out of two columns of this sheet.

        Used to load the two-column translation-dictionary spreadsheets
        (e.g. country name mappings) into lookup dicts.

        Args:
            key (int): Column index to use as dict keys.
            value (int): Column index to use as dict values.
            func_apply_key (Callable[[Any], Any] | None): Optional function
                applied to every key value before building the dict.
            func_apply_value (Callable[[Any], Any] | None): Optional function
                applied to every value before building the dict.

        Returns:
            dict[Any, Any]: The resulting key/value mapping.
        """
        val_col = self.dataframe[value]
        key_col = self.dataframe[key]

        if func_apply_value is not None:
            val_col = val_col.apply(func_apply_value)
        if func_apply_key is not None:
            key_col = key_col.apply(func_apply_key)

        return dict(zip(key_col, val_col, strict=True))

    def empty(self) -> None:
        """Drops all rows from the dataframe, keeping its columns/dtypes/header."""
        # retains columns, types, and headers if any, but 0 rows
        self.dataframe = self.dataframe[0:0].copy()

    def to_excel(self, output_path: Path) -> None:
        """
        Writes this dataframe out to an `.xlsx` file.

        Args:
            output_path (Path): Destination path for the spreadsheet.
        """
        self.dataframe.to_excel(output_path, index=False)
        logger.info(f"iMarina Excel at {output_path} built successfully.")

    def __copy__(self) -> Excel:
        """
        Returns a shallow copy of this `Excel` with an independently-copied
        dataframe.

        Returns:
            Excel: A new `Excel` instance wrapping a copy of `self.dataframe`.
        """
        empty = Excel(None)
        empty.dataframe = self.dataframe.copy()
        return empty

    def concat(self, excel: Excel) -> None:
        """
        Appends another `Excel`'s rows onto this one's dataframe, in place.

        Args:
            excel (Excel): The `Excel` whose rows are appended.
        """
        self.dataframe = pd.concat([self.dataframe, excel.dataframe], ignore_index=True)

__init__

__init__(path: Path | None, skiprows: int = 0, header: int | None = 0) -> None

Loads an Excel file into a dataframe, or starts with an empty one.

Parameters:

Name Type Description Default
path Path | None

Path to the .xlsx file to load, or None to start with an empty dataframe (used by __copy__).

required
skiprows int

Number of leading rows to skip before the header, forwarded to pandas.read_excel.

0
header int | None

Row index to use as the column header, forwarded to pandas.read_excel.

0
Source code in source/src/imarina_load_researchers/core/excel.py
def __init__(
    self,
    path: Path | None,
    skiprows: int = 0,
    header: int | None = 0,
) -> None:
    """
    Loads an Excel file into a dataframe, or starts with an empty one.

    Args:
        path (Path | None): Path to the `.xlsx` file to load, or `None`
            to start with an empty dataframe (used by `__copy__`).
        skiprows (int): Number of leading rows to skip before the header,
            forwarded to `pandas.read_excel`.
        header (int | None): Row index to use as the column header,
            forwarded to `pandas.read_excel`.
    """
    if path is None:
        self.dataframe = pd.DataFrame()
    else:
        self.dataframe = pd.read_excel(path, skiprows=skiprows, header=header)

parse_two_columns

parse_two_columns(key: int, value: int, func_apply_key: Callable[[Any], Any] | None = None, func_apply_value: Callable[[Any], Any] | None = None) -> dict[Any, Any]

Builds a {key: value} dict out of two columns of this sheet.

Used to load the two-column translation-dictionary spreadsheets (e.g. country name mappings) into lookup dicts.

Parameters:

Name Type Description Default
key int

Column index to use as dict keys.

required
value int

Column index to use as dict values.

required
func_apply_key Callable[[Any], Any] | None

Optional function applied to every key value before building the dict.

None
func_apply_value Callable[[Any], Any] | None

Optional function applied to every value before building the dict.

None

Returns:

Type Description
dict[Any, Any]

dict[Any, Any]: The resulting key/value mapping.

Source code in source/src/imarina_load_researchers/core/excel.py
def parse_two_columns(
    self,
    key: int,
    value: int,
    func_apply_key: Callable[[Any], Any] | None = None,
    func_apply_value: Callable[[Any], Any] | None = None,
) -> dict[Any, Any]:
    """
    Builds a `{key: value}` dict out of two columns of this sheet.

    Used to load the two-column translation-dictionary spreadsheets
    (e.g. country name mappings) into lookup dicts.

    Args:
        key (int): Column index to use as dict keys.
        value (int): Column index to use as dict values.
        func_apply_key (Callable[[Any], Any] | None): Optional function
            applied to every key value before building the dict.
        func_apply_value (Callable[[Any], Any] | None): Optional function
            applied to every value before building the dict.

    Returns:
        dict[Any, Any]: The resulting key/value mapping.
    """
    val_col = self.dataframe[value]
    key_col = self.dataframe[key]

    if func_apply_value is not None:
        val_col = val_col.apply(func_apply_value)
    if func_apply_key is not None:
        key_col = key_col.apply(func_apply_key)

    return dict(zip(key_col, val_col, strict=True))

empty

empty() -> None

Drops all rows from the dataframe, keeping its columns/dtypes/header.

Source code in source/src/imarina_load_researchers/core/excel.py
def empty(self) -> None:
    """Drops all rows from the dataframe, keeping its columns/dtypes/header."""
    # retains columns, types, and headers if any, but 0 rows
    self.dataframe = self.dataframe[0:0].copy()

to_excel

to_excel(output_path: Path) -> None

Writes this dataframe out to an .xlsx file.

Parameters:

Name Type Description Default
output_path Path

Destination path for the spreadsheet.

required
Source code in source/src/imarina_load_researchers/core/excel.py
def to_excel(self, output_path: Path) -> None:
    """
    Writes this dataframe out to an `.xlsx` file.

    Args:
        output_path (Path): Destination path for the spreadsheet.
    """
    self.dataframe.to_excel(output_path, index=False)
    logger.info(f"iMarina Excel at {output_path} built successfully.")

__copy__

__copy__() -> Excel

Returns a shallow copy of this Excel with an independently-copied dataframe.

Returns:

Name Type Description
Excel Excel

A new Excel instance wrapping a copy of self.dataframe.

Source code in source/src/imarina_load_researchers/core/excel.py
def __copy__(self) -> Excel:
    """
    Returns a shallow copy of this `Excel` with an independently-copied
    dataframe.

    Returns:
        Excel: A new `Excel` instance wrapping a copy of `self.dataframe`.
    """
    empty = Excel(None)
    empty.dataframe = self.dataframe.copy()
    return empty

concat

concat(excel: Excel) -> None

Appends another Excel's rows onto this one's dataframe, in place.

Parameters:

Name Type Description Default
excel Excel

The Excel whose rows are appended.

required
Source code in source/src/imarina_load_researchers/core/excel.py
def concat(self, excel: Excel) -> None:
    """
    Appends another `Excel`'s rows onto this one's dataframe, in place.

    Args:
        excel (Excel): The `Excel` whose rows are appended.
    """
    self.dataframe = pd.concat([self.dataframe, excel.dataframe], ignore_index=True)

get_val

get_val(row: Series, field: str) -> Any

Reads a cell value from a dataframe row, normalizing pandas' NaN to None.

Parameters:

Name Type Description Default
row Series

The row to read from.

required
field str

The column/field name to read.

required

Returns:

Name Type Description
Any Any

The cell value, or None if it's NaN/missing.

Source code in source/src/imarina_load_researchers/core/excel.py
def get_val(row: pd.Series, field: str) -> Any:
    """
    Reads a cell value from a dataframe row, normalizing pandas' NaN to `None`.

    Args:
        row (pd.Series): The row to read from.
        field (str): The column/field name to read.

    Returns:
        Any: The cell value, or `None` if it's `NaN`/missing.
    """
    val = row[field]
    if pd.isna(val):
        return None
    return val

get_str_val

get_str_val(row: Series, field: str) -> str

Reads a cell value from a dataframe row as a stripped string.

Parameters:

Name Type Description Default
row Series

The row to read from.

required
field str

The column/field name to read.

required

Returns:

Name Type Description
str str

The cell value converted to str and stripped, or "" if the cell is NaN/missing.

Source code in source/src/imarina_load_researchers/core/excel.py
def get_str_val(row: pd.Series, field: str) -> str:
    """
    Reads a cell value from a dataframe row as a stripped string.

    Args:
        row (pd.Series): The row to read from.
        field (str): The column/field name to read.

    Returns:
        str: The cell value converted to `str` and stripped, or `""` if the
            cell is `NaN`/missing.
    """
    val = get_val(row, field)
    return str(val).strip() if val is not None else ""