This brief post provides the R syntax to calculate SF-12 v2 scores using Australian population weights.

The population weights are derived from:

Hawthorne, G., Osborne, R., Taylor, A., & Sansoni, J. (2007). The SF36 Version 2: critical analyses of population weights, scoring algorithms and population norms. Quality of Life Research, 16(4), 661-673. doi: 10.1007/s11136-006-9154-4

Please rename the df_sf12 to reflect the name of the data set you are using.

Please note that the variable names need to conform to the survey item names:

  • I1, I2A, I2B, I3A, I4A, I4B, I5, I6A, I6B, I6C, and I7

Code

# -------------------------------------------------------------------------
# Project: SF-12 v2.0 Scoring using Australian Population Weights
#
# Coded by: Sam Mancuso
# Web: sammancuso.com
#
# Date: 9 November 2017
# Version: 2.00
# Notes: Updated to use tidyverse
# -------------------------------------------------------------------------

# Australian Population Weights
# ------------------------------
# Hawthorne, G., Osborne, R., Taylor, A., & Sansoni, J. (2007). The SF36
# Version 2: critical analyses of population weights, scoring algorithms
# and population norms. Quality of Life Research, 16(4), 661-673.
# doi: 10.1007/s11136-006-9154-4

# Assumes variable names conform to survey:
#
# I1, I2A, I2B, I3A, I4A, I4B, I5, I6A, I6B, I6C, and I7

# Install/Load Required Packages ----
if (!require(pacman)) {
  install.packages("pacman")
}
pacman::p_load(tidyverse)

# Scoring ----
df_sf12 %>%
  # Recode items, 1, 5, 6a, and 6b
  mutate(
    I1r = recode(
      I1, 
      `1` = 5, 
      `2` = 4.4, 
      `3` = 3.4, 
      `4` = 2.0, 
      `5` = 1.0
      ),
    I5r = 6 - I5,
    I6Ar = 6 - I6A,
    I6Br = 6 - I6B
  ) %>%
  # Transform raw scores:
  # PF = Physical Functioning
  # RP = Role Physical
  # BP = Bodily Pain
  # GH = General Health
  # VT = Vitality
  # SF = Social Functioning
  # RE = Role Emotional
  # MH = Mental Health
  mutate(
    PF = ((I2A + I2B - 2) / 4) * 100,
    RP = ((I3A + I3B - 2) / 8) * 100,
    BP = ((I5r - 1) / 4) * 100,
    GH = ((I1r - 1) / 4) * 100,
    VT = ((I6Br - 1) / 4) * 100,
    SF = ((I7 - 1) / 4) * 100,
    RE = ((I4A + I4B - 2) / 8) * 100,
    MH = ((I6Ar + I6C - 2) / 8) * 100
  ) %>%
  # Standardisation of SF-12v2 Scores
  mutate(
    PF_Z = (PF - 84.64) / 21.86,
    RP_Z = (RP - 84.41) / 25.13,
    BP_Z = (BP - 76.45) / 21.24,
    GH_Z = (GH - 71.90) / 21.88,
    VT_Z = (VT - 61.12) / 20.80,
    SF_Z = (SF - 86.19) / 22.33,
    RE_Z = (RE - 91.59) / 17.50,
    MH_Z = (MH - 80.63) / 16.99
  ) %>%
  # Physical and Mental Component Scores
  mutate(
    AGG_PHYS = (PF_Z * 0.409) +
      (RP_Z * 0.325) +
      (BP_Z * 0.289) +
      (GH_Z * 0.231) +
      (VT_Z * 0.106) +
      (SF_Z * 0.014) +
      (RE_Z * -.183) +
      (MH_Z * -.205),
    AGG_MENT = (PF_Z * -.224) +
      (RP_Z * -.096) +
      (BP_Z * -.105) +
      (GH_Z * 0.001) +
      (VT_Z * 0.157) +
      (SF_Z * 0.249) +
      (RE_Z * 0.449) +
      (MH_Z * 0.476)
  ) %>%
  # Convert to T-Scores
  mutate(
    PF_T = 50 + (10 * PF_Z),
    RP_T = 50 + (10 * RP_Z),
    BP_T = 50 + (10 * BP_Z),
    GH_T = 50 + (10 * GH_Z),
    VT_T = 50 + (10 * VT_Z),
    SF_T = 50 + (10 * SF_Z),
    RE_T = 50 + (10 * RE_Z),
    MH_T = 50 + (10 * MH_Z),
    AGG_PHYS_T = 50 + (10 * AGG_PHYS),
    AGG_MENT_T = 50 + (10 * AGG_MENT)
  )

Note

Some users of the code advised me that they may get negative scores for respondents when using these weights. While I recommend converting the negative values to zero, you should run a sensitivity analysis to compare the results you obtain with negative values to those you obtain with zero values. Based on the feedback from these users, it seems that changing the negative values to zero does not impact their results.