Appendix A: GSS data

The social-science examples in this book use the General Social Survey (GSS), a survey of adults in the United States conducted by NORC at the University of Chicago since 1972. The GSS data are free to download, and no registration is required.

We start with the simplest version of the data: one survey year, a few dozen variables, and categories stored as ordinary factors. This is a one-time preparation recipe: run it in order, read each step, and keep the script, but do not treat its technical cleaning functions as a list to memorize before exploring the survey. The practical chapters teach the everyday table operations separately. Combining several survey years is planned for later teaching and is outside this edition.

A.1 Installing gssr

The gssr package by Kieran Healy downloads GSS data directly into R. Install it once from R-universe. The argument repos gives the locations where install.packages() searches: Healy’s R-universe repository and CRAN here. c() combines the two quoted addresses into a character vector:

install.packages(
  "gssr",
  repos = c("https://kjhealy.r-universe.dev", "https://cloud.r-project.org")
)

A.2 Downloading one survey year

Work in the r4ss folder established in Section 1.1.1. Check getwd() before beginning and save these steps in a script called prepare-gss.R there. They acquire, prepare, and save the extract once. In later sessions, you only load the saved result.

Load tidyverse, tidystata, and gssr. gss_get_yr(2024) is the download step: it retrieves the 2024 survey from NORC and returns a table. Assignment stores it as gss_raw, keeping the original values available while we prepare a separate extract:

library(tidyverse)
library(tidystata)
library(gssr)
gss_raw <- gss_get_yr(2024)
nrow(gss_raw)

nrow() reports the number of respondents. The release used here has 3986 respondents; the raw download has many more columns than we need. Let the download finish before running the next step. A network error means no new table was returned: check the connection and error message, then retry that step. If a new release has different dimensions, inspect its documentation before assuming it is the same extract. Download time depends on the connection and server.

A.3 Keeping the book’s variables

Here, |> passes the table on its left as the first input to the next function. Dplyr’s select() keeps named columns in the order written, leaving rows unchanged. Column names inside select() are unquoted. We assign its returned table to gss24, without changing gss_raw:

gss24 <- gss_raw |>
  select(
    id, age, sex, race, region,
    degree, educ, paeduc, maeduc,
    marital, childs, wrkstat, hrs1, realinc,
    polviews, partyid, happy, health,
    conbus, coneduc, conmedic, conpress, consci, conlegis,
    wtssps
  )

Expect 3986 rows and 25 columns for this release. If a name cannot be found, compare the download’s names with this list; do not substitute a similarly named variable without checking its meaning. The descriptions below explain the variables we keep.

A.4 Preparing missing values and categories

Imported columns can contain numeric codes with value labels. A code for “don’t know” is not a real age or degree. Haven’s zap_missing() turns special missing values recognized in the imported file into ordinary R missing values, NA. It does not decide that an arbitrary number is missing: its behavior relies on the file’s declared missing values, which should be checked against the codebook.

The function can clean the complete table directly:

gss24 <- haven::zap_missing(gss24)

Values have been marked missing; no respondents have been deleted. Next, turn the named categorical variables into factors, which store categories and their possible levels. Quantities such as age and schooling remain numeric.

mutate() returns a table with changed columns. Within it, across() applies the same conversion to several selected columns. c() groups the names, and the familiar starts_with("con") identifies the confidence items. The short function \(x) receives each column, converts its value labels to categories with haven::as_factor(), and passes that result to fct_drop() to remove unused levels. Dropping a level does not delete respondents. as.integer() stores the respondent ID as whole numbers.

gss24 <- gss24 |>
  mutate(
    across(
      c(sex, race, region, degree, marital, wrkstat, polviews, partyid,
        happy, health, starts_with("con")),
      \(x) fct_drop(haven::as_factor(x))
    ),
    id = as.integer(id)
  )

The conversion keeps the source-code order of categories, rather than sorting their labels alphabetically. That order is used in the book’s frequency tables. It does not assert equal distances between categories.

Finally, remove the remaining source-software metadata. zap_labels() removes value-label definitions from numeric columns, leaving the factors already created intact. zap_label() removes descriptive variable-label attributes, and zap_formats() removes display formats. These cleanup steps preserve the recorded values; the variable descriptions below retain their meanings.

gss24 <- gss24 |>
  haven::zap_labels() |>
  haven::zap_label() |>
  haven::zap_formats()

Use the inspection tools from Section 7.5 to check the result:

nrow(gss24)
ncol(gss24)
codebook(gss24, id, age, degree)
isid(gss24, id)

Expect 3986 respondents and 25 variables. ID is integer, age is numeric, and degree is a factor. Tidystata’s isid() checks that the selected ID column uniquely identifies every row and has no missing identifiers. It prints a confirmation and returns the complete table invisibly without changing values or row order; an invalid key raises an error. This verifies the extract’s one-row-per-respondent structure. The observed age count excludes unavailable answers; preparation preserves those missing values. If dimensions, types, or category meanings differ, check the source release and the steps above before analysis.

A.5 Saving and resuming

We use RDS because it retains the prepared column types and factor levels when the table is restored in R. This preserves the preparation for later chapters. Chapter 18 compares formats for sharing data with other software.

Base R’s saveRDS() writes one R object to disk. Save the prepared table directly in your project folder:

saveRDS(gss24, "gss24.rds")
file.exists("gss24.rds")

Saving is silent; the check should return TRUE. Locate gss24.rds in the folder reported by getwd(). Keep the preparation script too, so you can rebuild the extract. You do not need to download and transform it again for each chapter.

In a later session, open the same project folder, check getwd(), and load the packages used by that chapter. Restore the object with base R’s readRDS():

gss24 <- readRDS("gss24.rds")

This recreates the table in memory. If R cannot open it, use file.exists("gss24.rds") and getwd() to check its location before repeating the download.

A.6 Variables

Table A.1: Variables in gss24. Descriptions follow the GSS variable labels.
Variable Description
id Respondent ID number
age Age in years
sex Sex
race Race
region Region of interview
degree Highest degree
educ Highest year of school completed
paeduc, maeduc Highest year of school completed by the father and the mother (for same-sex parents, the older and the younger parent)
marital Marital status
childs Number of children
wrkstat Labor force status
hrs1 Hours worked last week
realinc Family income adjusted for price changes to 1986 purchasing power
polviews Political views, from extremely liberal to extremely conservative
partyid Political party affiliation
happy General happiness
health Self-rated health
conbus, coneduc, conmedic, conpress, consci, conlegis Confidence in major companies, education, medicine, the press, the scientific community, and Congress
wtssps Person post-stratification weight; adjusts each respondent’s contribution when estimating population quantities

The GSS does not ask every question of every respondent. A ballot here means a version of the questionnaire. The confidence questions, for example, were asked on two of the three 2024 ballots, so about a third of their values are missing by design.

A.7 Citing the GSS

NORC asks users to cite the data as follows:

Davern, Michael; Bautista, Rene; Freese, Jeremy; Herd, Pamela; and Morgan, Stephen L. General Social Survey 1972-2024. [Machine-readable data file]. Principal Investigator, Michael Davern; Co-Principal Investigators, Rene Bautista, Jeremy Freese, Pamela Herd, and Stephen L. Morgan. NORC ed. Chicago, 2026. 1 datafile and 1 codebook (2024 Release 3a).

This book does not redistribute GSS data. The code above downloads the data directly from NORC; see NORC’s terms and conditions.