Work Productivity and Activity Impairment (WPAI)
A patient-reported outcome framework that expresses recent health-related work absence, impairment while working, overall work impairment, and impairment in regular non-work activities as percentages; it measures productivity impact and does not itself assign a monetary value.
On this page
WPAI is a short patient questionnaire that asks how health affected work and usual activities during the past week. It reports percentages for missed work, difficulty while at work, their combined work effect, and difficulty in regular activities. Those percentages describe impairment; they are not dollars until a separate, explicit valuation method is chosen.
Work Productivity and Activity Impairment (WPAI)
captures how health affects paid work and regular activities over a 7-day recall period. The WPAI General Health (WPAI:GH) asks about employment, work time missed because of health, time missed for other reasons, time actually worked, impairment while working, and impairment in regular activities. Disease-specific WPAI versions retain the same scoring structure but attribute impairment to the named health problem. The derived domains are percentages from 0 to 100, where higher values mean more impairment.
Use the developer scoring rules, not a home-made sum
Health-related absenteeism is health-related hours missed divided by health-related missed hours plus hours actually worked. Presenteeism is the reported on-the-job impairment rating divided by 10. Overall work impairment combines absence and impairment during time worked: absenteeism + (1 - absenteeism) × presenteeism. Activity impairment is its separate 0-to-10 rating divided by 10 and applies whether or not someone is employed. Do not add the percentages: overall work impairment already accounts for both components.
Employment, denominator, and missing-item rules matter
Score each work domain from its own required inputs rather than discarding every work score because one item is absent. Absenteeism requires valid health-missed and worked hours with a positive denominator. Presenteeism requires a valid on-the-job impairment rating and known positive worked hours for a respondent eligible for work-domain assessment; a missing health-missed-hours response does not by itself erase that valid rating. Overall work impairment requires the component inputs, except that when all observed scheduled time was missed for health (health-missed hours > 0 and worked hours = 0), absenteeism and overall work impairment are 100% and presenteeism is not applicable. A respondent who is not employed has no work-domain score; never convert that to 0% impairment. Activity impairment remains independently scorable for employed and non-employed respondents. Preserve the instrument version, language, attribution (general health or condition-specific), recall period, completion date, and the reason a score is absent.
Measurement is not monetary valuation
WPAI reports perceived time and productivity impairment. Converting it to money requires additional choices: wage source, fringe benefits, employer replacement costs, labor-force participation, and whether to use a human-capital or friction-cost perspective. A 20% WPAI overall-work-impairment score is not automatically 20% of salary lost, and it should not be combined with claims-paid amounts without a stated perspective and double-counting assessment.
Pros, cons, and trade-offs
WPAI is brief, understandable, and can capture productivity impact that claims omit. Its cost is self-report and a short recall window; results may be affected by disease severity, occupation, benefit design, remote work, and cultural or language context. Relative to HRQoL measures that produce preference-weighted utilities, WPAI describes functional/productivity consequences rather than health utility. Relative to burden-of-disease-cost-of-illness, it supplies an input to indirect-cost estimation but does not by itself estimate societal cost.
When NOT to use — and when it is actively misleading
Do not use WPAI to infer productivity from claims, diagnosis codes, or employment status. Do not report a work-domain mean across all enrolled people while silently treating non-employed participants as zero impairment. Do not substitute a disease-specific WPAI score for a general-health score, or vice versa, without saying which attribution question was asked. Do not reproduce the proprietary questionnaire items or assume that a translated or modified instrument remains validated.
Data-source operational depth
- Survey / ePRO: The native source. Preserve raw permitted item responses, version/language, completion timestamp, and 7-day recall anchor; apply developer-authorized scoring only.
- EHR: EHRs may hold a completed questionnaire but generally cannot reconstruct valid WPAI domains from visit notes. Employment fields are not equivalent to the instrument's employment and time responses.
- Claims: Claims can measure direct medical spending but cannot observe absence, presenteeism, or activity impairment. Employer claims or disability feeds require separate validation and still do not produce WPAI without the questionnaire.
- Registry / linked data: Link survey/ePRO scores to clinical and claims data with explicit consent, date alignment, and linkage-availability reporting. The linked subset may differ in employment, severity, and response propensity.
Decision diagram
%%{init: {'themeVariables': {'fontSize': '16px'}, 'flowchart': {'nodeSpacing': 18, 'rankSpacing': 24}}}%%
flowchart TD
A["Authorized version<br/>and 7-day recall"] --> B["Adjudicate employment<br/>Assess each domain separately"]
B --> C["Absenteeism<br/>Health-missed / total work hours<br/>Positive denominator required"]
C --> D["Presenteeism<br/>At-work rating / 10<br/>Positive worked hours required"]
D --> E["Overall work impairment<br/>Combine available components<br/>All work missed for health: 100%"]
E --> F["Activity impairment<br/>Activity rating / 10<br/>Employment not required"]
F --> G["Report domain percentages<br/>and missingness separately"]Index definitions
Source-backed definitions and variants for the index or checklist family.
| name | definition | source | use | notes |
|---|---|---|---|---|
| Recall and attribution | WPAI:GH uses a 7-day recall and attributes impairment to health in general; disease-specific versions use the same domain framework but name the health problem. | HCV RWE PMOS SAP (developer coding rules applied) | Choose one pre-specified version and report it exactly. | Do not pool general-health and condition-specific scores as if they answer the same question. |
| Absenteeism | 100 × health-related hours missed / (health-related hours missed + hours actually worked). | HCV RWE PMOS SAP (developer coding rules applied) | Report when valid health-missed and worked hours give a positive denominator for a work-domain-eligible respondent. | Do not substitute time missed for other reasons into the health-related numerator. When health-missed hours are positive and worked hours are zero, absenteeism is 100%. |
| Presenteeism | 100 × impairment-while-working rating / 10. | HCV RWE PMOS SAP (developer coding rules applied) | Report for work-domain-eligible respondents with known positive worked hours and a valid impairment rating; missing health-missed hours alone do not invalidate presenteeism. | Higher scores indicate worse impairment. It requires known positive worked hours and is not applicable when the respondent worked zero hours because all observed scheduled time was missed for health. |
| Overall work impairment | 100 × [absenteeism proportion + (1 - absenteeism proportion) × presenteeism proportion]. | HCV RWE PMOS SAP (developer coding rules applied) | Combine valid absence and at-work impairment inputs for eligible employed respondents. | Do not add the two percentage scores because that double-counts impairment during absent time. If health-missed hours are positive and worked hours are zero, overall work impairment is 100% without an at-work rating. |
| Activity impairment | 100 × regular-activity impairment rating / 10. | OPALE P15-405 SAP, page 39 (documented WPAI scoring implementation) | Report independently for all respondents with a valid activity rating. | It is not restricted to employed people. |
Worked example
Scenario
A 7-day disease-specific WPAI assessment is completed at baseline by four people in an RWE registry. The study will report health-related work impairment separately from activity impairment and will not monetize the score.
Dataset
Synthetic score inputs; numbers are permitted responses and not questionnaire text.
| person_id | employed | health_missed_hours | worked_hours | at_work_impairment_0_to_10 | activity_impairment_0_to_10 |
|---|---|---|---|---|---|
| 101 | yes | 4 | 28 | 5 | 6 |
| 102 | yes | 0 | 0 | 8 | |
| 103 | no | 4 | |||
| 104 | yes | 4 | 0 | 5 |
Steps
Result
The study reports work outcomes among score-eligible employed respondents and activity impairment among all valid respondents. It does not describe the non-employed group as having zero work impairment or turn the percentages into dollars without a separate valuation model.
Trade-offs
Code example
Execution not verified · inspect inputs and dependencies before use
Runnable arithmetic scorer for adjudicated employment and permitted WPAI numeric inputs: health_missed_hours, worked_hours, at_work_impairment_0_to_10, and activity_impairment_0_to_10. It scores each domain independently, returns None for unavailable or invalid domains, and does not recode raw questionnaire...
import math
def wpai_scores(employed, health_missed_hours, worked_hours,
at_work_impairment_0_to_10, activity_impairment_0_to_10):
def valid_nonnegative(value):
return isinstance(value, (int, float)) and math.isfinite(value) and value >= 0
def scale_0_10(value):
return 100 * value / 10 if valid_nonnegative(value) and value <= 10 else None
activity = scale_0_10(activity_impairment_0_to_10)
eligible = employed is True
valid_hours = valid_nonnegative(health_missed_hours) and valid_nonnegative(worked_hours)
denom = health_missed_hours + worked_hours if valid_hours else None
absenteeism = (100 * health_missed_hours / denom
if eligible and denom is not None and denom > 0 else None)
presenteeism = (scale_0_10(at_work_impairment_0_to_10)
if eligible and valid_nonnegative(worked_hours) and worked_hours > 0 else None)
if eligible and valid_hours and health_missed_hours > 0 and worked_hours == 0:
overall = 100.0
elif absenteeism is not None and presenteeism is not None:
overall = absenteeism + (100 - absenteeism) * presenteeism / 100
else:
overall = None
return {"absenteeism": absenteeism, "presenteeism": presenteeism,
"overall_work_impairment": overall, "activity_impairment": activity}
synthetic_responses = [
{"employed": True, "health_missed_hours": 4, "worked_hours": 28,
"at_work_impairment_0_to_10": 5, "activity_impairment_0_to_10": 6},
{"employed": True, "health_missed_hours": None, "worked_hours": 28,
"at_work_impairment_0_to_10": 7, "activity_impairment_0_to_10": 8},
{"employed": True, "health_missed_hours": 4, "worked_hours": 0,
"at_work_impairment_0_to_10": None, "activity_impairment_0_to_10": 5},
{"employed": False, "health_missed_hours": None, "worked_hours": None,
"at_work_impairment_0_to_10": None, "activity_impairment_0_to_10": 4},
]
print([wpai_scores(**row) for row in synthetic_responses])Execution not verified · inspect inputs and dependencies before use
Runnable base-R arithmetic scorer for the same adjudicated employment and permitted numeric WPAI inputs.
wpai_scores <- function(employed, health_missed_hours, worked_hours,
at_work_impairment_0_to_10, activity_impairment_0_to_10) {
valid_nonnegative <- function(x) length(x) == 1L && is.finite(x) && x >= 0
scale_0_10 <- function(x) if (!valid_nonnegative(x) || x > 10) NA_real_ else 100 * x / 10
activity <- scale_0_10(activity_impairment_0_to_10)
eligible <- isTRUE(employed)
valid_hours <- valid_nonnegative(health_missed_hours) && valid_nonnegative(worked_hours)
denom <- if (valid_hours) health_missed_hours + worked_hours else NA_real_
absenteeism <- if (eligible && valid_hours && denom > 0) 100 * health_missed_hours / denom else NA_real_
presenteeism <- if (eligible && valid_nonnegative(worked_hours) && worked_hours > 0) scale_0_10(at_work_impairment_0_to_10) else NA_real_
overall <- if (eligible && valid_hours && health_missed_hours > 0 && worked_hours == 0) 100 else if (!is.na(absenteeism) && !is.na(presenteeism)) absenteeism + (100 - absenteeism) * presenteeism / 100 else NA_real_
c(absenteeism=absenteeism, presenteeism=presenteeism,
overall_work_impairment=overall,
activity_impairment=activity)
}
synthetic_responses <- data.frame(
employed = c(TRUE, TRUE, TRUE, FALSE), health_missed_hours = c(4, NA, 4, NA),
worked_hours = c(28, 28, 0, NA), at_work_impairment_0_to_10 = c(5, 7, NA, NA),
activity_impairment_0_to_10 = c(6, 8, 5, 4)
)
t(mapply(wpai_scores, synthetic_responses$employed, synthetic_responses$health_missed_hours,
synthetic_responses$worked_hours, synthetic_responses$at_work_impairment_0_to_10,
synthetic_responses$activity_impairment_0_to_10))Execution not verified · inspect inputs and dependencies before use
SAS DATA-step arithmetic scorer. Input `wpai` has adjudicated employed (0/1), health_missed_hours, worked_hours, at_work_impairment_0_to_10, and activity_impairment_0_to_10. Missing work scores mean unavailable or invalid; they are not zero impairment.
data wpai_scored;
set wpai;
if not missing(activity_impairment_0_to_10) and activity_impairment_0_to_10 >= 0 and activity_impairment_0_to_10 <= 10 then activity_impairment = 10*activity_impairment_0_to_10;
else activity_impairment = .;
absenteeism = .; presenteeism = .; overall_work_impairment = .;
valid_hours = not missing(health_missed_hours) and not missing(worked_hours)
and health_missed_hours >= 0 and worked_hours >= 0;
if valid_hours then work_denom = health_missed_hours + worked_hours;
else work_denom = .;
if employed=1 and valid_hours and work_denom > 0 then absenteeism = 100*health_missed_hours/work_denom;
if employed=1 and not missing(worked_hours) and worked_hours > 0
and not missing(at_work_impairment_0_to_10) and at_work_impairment_0_to_10 >= 0
and at_work_impairment_0_to_10 <= 10 then presenteeism = 10*at_work_impairment_0_to_10;
if employed=1 and valid_hours and health_missed_hours > 0 and worked_hours=0 then overall_work_impairment = 100;
else if not missing(absenteeism) and not missing(presenteeism) then do;
overall_work_impairment = absenteeism + (100-absenteeism)*presenteeism/100;
end;
run;