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: 30afternoon: 30evening: 30night: 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 |
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
|
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 |
0
|
missing_policy
|
str
|
How to handle missing values in
|
'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 |
ValueError
|
If |
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 |
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
|
'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 |
ValueError
|
If |
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'
|
weekly_col
|
str
|
Column containing percentage weekly availability. The default is
|
'perc_weekly_avail'
|
output_col
|
str
|
Name of the output column containing overall vendor availability. The
default is |
'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 |
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",
... )