Skip to content

Availability

The availability module provides functions for constructing vendor availability indicators used in the Nutrition-Sensitive Food Environment Index (N-FEI).

In food environment analysis, availability is not only defined by whether a vendor exists, but also by how consistently that vendor is accessible to consumers throughout the day and across the week. Vendors that operate only during limited hours or on selected days may contribute less to effective food access than vendors that are continuously available.

This module operationalizes availability using two complementary dimensions:

  • Daily availability, which captures access across different time periods within a day (morning, afternoon, evening, and night), using a weighted approach that reflects typical consumer purchasing patterns.
  • Weekly availability, which captures access across days of the week, reflecting how consistently vendors operate over time.

These two components can be combined into a single overall vendor availability indicator, providing a more complete representation of temporal access to food vendors.

The functions in this module are designed to work with survey-based data where availability is recorded as binary indicators across time periods or days. They also explicitly account for survey designs where “all day” or “all week” responses replace detailed time or day-level inputs.

Daily availability

add_daily_availability(df: DataFrame, time_cols: dict[str, str], all_day_col: str | None = None, time_weights: dict[str, float] | None = None, output_col: str = 'perc_daily_avail', fillna_value: int | float = 0, missing_policy: str = 'raise') -> pd.DataFrame

This function computes the daily component of vendor availability used in the NFEI workflow. It converts binary time-period availability columns into a percentage score that reflects the share of the day during which a vendor is accessible to consumers.

By default, the function follows the NFEI notebook weighting scheme:

  • morning: 30
  • afternoon: 30
  • evening: 30
  • night: 10

These weights reflect the assumption that most food purchasing activity occurs from morning to evening, while night-time availability contributes a smaller share to overall daily access.

Parameters:

Name Type Description Default
df DataFrame

Input dataframe.

required
time_cols dict[str, str]

Dictionary mapping the required time-period labels to dataframe column names. The required keys are "morning", "afternoon", "evening", and "night".

required
all_day_col str | None

Optional binary column indicating whether the vendor operates all day. If provided and equal to 1, the daily availability score is set to 100.

None
time_weights dict[str, float] | None

Optional dictionary mapping the same time-period labels in time_cols to percentage weights. If None, the default NFEI weights are used. Custom weights must use the same keys as time_cols. Users should ensure the weights sum to 100 for direct percentage interpretation.

None
output_col str

Name of the output daily availability column.

'perc_daily_avail'
fillna_value int | float

Value used to fill missing values when missing_policy="fill".

0
missing_policy str

How to handle missing values in time_cols.

  • "raise": raise an error for missing time values unless all_day_col == 1.
  • "fill": fill missing time values with fillna_value.
  • "ignore": leave missing values as-is.
'raise'

Returns:

Type Description
DataFrame

Copy of the dataframe with the daily availability percentage column added.

Raises:

Type Description
KeyError

If any required time-period column, or the optional all_day_col, is not found in the dataframe.

ValueError

If time_cols and time_weights do not contain the same keys, if missing_policy is invalid, or if missing values are found under missing_policy="raise".

Notes

Missing values are handled conservatively by default. When missing_policy="raise", missing values in time_cols are allowed only for rows where all_day_col == 1. This supports survey designs where time-period questions are skipped after an all-day response.

If all_day_col is not provided, missing values in time_cols are treated as a data-quality issue unless missing_policy="fill" or missing_policy="ignore" is used.

Examples:

Standard use with an all-day column:

>>> import pandas as pd
>>> import nfei
>>>
>>> df = pd.DataFrame(
...     {
...         "vendor_allday": [0, 1],
...         "available_morning": [1, None],
...         "available_afternoon": [1, None],
...         "available_evening": [0, None],
...         "available_night": [0, None],
...     }
... )
>>> time_cols = {
...     "morning": "available_morning",
...     "afternoon": "available_afternoon",
...     "evening": "available_evening",
...     "night": "available_night",
... }
>>> result = nfei.add_daily_availability(
...     df,
...     time_cols=time_cols,
...     all_day_col="vendor_allday",
... )

Custom weighting:

>>> result = nfei.add_daily_availability(
...     df,
...     time_cols=time_cols,
...     all_day_col="vendor_allday",
...     time_weights={
...         "morning": 25,
...         "afternoon": 25,
...         "evening": 25,
...         "night": 25,
...     },
... )

Weekly availability

add_weekly_availability(df: DataFrame, day_cols: list[str], all_week_col: str | None = None, output_col: str = 'perc_weekly_avail', days_in_week: int = 7, fillna_value: int | float = 0, round_result: bool = False, missing_policy: str = 'raise') -> pd.DataFrame

This function computes the weekly component of vendor availability used in the NFEI workflow. It converts binary day-of-week availability columns into a percentage score that reflects how consistently a vendor is accessible across the week.

By default, the function expects seven binary day columns, one for each day of the week, and calculates availability as:

number of available days / days_in_week * 100

If all_week_col is provided and equals 1, weekly availability is set to 100, even if the individual day columns are missing. This supports survey designs where individual day questions are skipped after an all-week response.

Parameters:

Name Type Description Default
df DataFrame

Input dataframe.

required
day_cols list[str]

List of binary day-of-week columns. By default, this should contain seven columns, one for each day of the week.

required
all_week_col str | None

Optional binary column indicating whether the vendor operates all week. If provided and equal to 1, the weekly availability score is set to 100.

None
output_col str

Name of the output weekly availability column.

'perc_weekly_avail'
days_in_week int

Number of days used as the denominator. The default is 7.

7
fillna_value int | float

Value used to fill missing values when missing_policy="fill".

0
round_result bool

If True, converts the weekly availability score to an integer percentage. This is useful when matching notebook workflows where percentage availability was stored as rounded whole numbers.

False
missing_policy str

How to handle missing values in day_cols.

  • "raise": raise an error for missing day values unless all_week_col == 1.
  • "fill": fill missing day values with fillna_value.
  • "ignore": leave missing values as-is.
'raise'

Returns:

Type Description
DataFrame

Copy of the dataframe with the weekly availability percentage column added.

Raises:

Type Description
KeyError

If any required day column, or the optional all_week_col, is not found in the dataframe.

ValueError

If days_in_week is less than or equal to zero, if the number of day_cols does not match days_in_week, if missing_policy is invalid, or if missing values are found under missing_policy="raise".

Notes

The default configuration assumes a standard seven-day week. If a different denominator is used, day_cols must contain the same number of columns as days_in_week.

Missing values are handled conservatively by default. When missing_policy="raise", missing values in day_cols are allowed only for rows where all_week_col == 1.

If all_week_col is not provided, missing values in day_cols are treated as a data-quality issue unless missing_policy="fill" or missing_policy="ignore" is used.

Examples:

Standard use with an all-week column:

>>> import pandas as pd
>>> import nfei
>>>
>>> df = pd.DataFrame(
...     {
...         "vendor_allweek": [0, 1],
...         "monday": [1, None],
...         "tuesday": [1, None],
...         "wednesday": [1, None],
...         "thursday": [0, None],
...         "friday": [0, None],
...         "saturday": [0, None],
...         "sunday": [0, None],
...     }
... )
>>> day_cols = [
...     "monday",
...     "tuesday",
...     "wednesday",
...     "thursday",
...     "friday",
...     "saturday",
...     "sunday",
... ]
>>> result = nfei.add_weekly_availability(
...     df,
...     day_cols=day_cols,
...     all_week_col="vendor_allweek",
... )

Use without an all-week column when all day columns are collected directly:

>>> df = pd.DataFrame(
...     {
...         "monday": [1],
...         "tuesday": [1],
...         "wednesday": [1],
...         "thursday": [0],
...         "friday": [0],
...         "saturday": [0],
...         "sunday": [0],
...     }
... )
>>> result = nfei.add_weekly_availability(
...     df,
...     day_cols=day_cols,
...     all_week_col=None,
...     round_result=True,
... )

Overall vendor availability

add_vendor_availability(df: DataFrame, daily_col: str = 'perc_daily_avail', weekly_col: str = 'perc_weekly_avail', output_col: str = 'perc_vendor_avail') -> pd.DataFrame

This function computes the combined vendor availability indicator used in the NFEI workflow. It summarizes temporal access to vendors by taking the row-wise mean of daily availability and weekly availability.

The function assumes that daily and weekly availability have already been computed, typically using :func:add_daily_availability and :func:add_weekly_availability. The resulting score provides a single percentage-based measure of how consistently a vendor is available both within a day and across the week.

Parameters:

Name Type Description Default
df DataFrame

Input dataframe.

required
daily_col str

Column containing percentage daily availability. The default is "perc_daily_avail".

'perc_daily_avail'
weekly_col str

Column containing percentage weekly availability. The default is "perc_weekly_avail".

'perc_weekly_avail'
output_col str

Name of the output column containing overall vendor availability. The default is "perc_vendor_avail".

'perc_vendor_avail'

Returns:

Type Description
DataFrame

Copy of the input dataframe with the combined vendor availability column added.

Raises:

Type Description
KeyError

If either daily_col or weekly_col is not found in the dataframe.

Notes

The output is calculated as:

(daily availability + weekly availability) / 2

The function does not rescale the inputs. Users should ensure that both input columns are measured on the same percentage scale, usually 0 to 100.

Examples:

Standard use with default column names:

>>> import pandas as pd
>>> import nfei
>>>
>>> df = pd.DataFrame(
...     {
...         "perc_daily_avail": [100, 60],
...         "perc_weekly_avail": [100, 40],
...     }
... )
>>> result = nfei.add_vendor_availability(df)

Use with custom column names:

>>> result = nfei.add_vendor_availability(
...     df,
...     daily_col="perc_daily_avail",
...     weekly_col="perc_weekly_avail",
...     output_col="vendor_availability_score",
... )