# SIPP data are in person-month format, meaning each record represents one month for a specific person.
# Unique persons are identified using SSUID+PNUM. Unique households are identified using SSUID+ERESIDENCEID. For
# additional guidance on using SIPP data, please see the SIPP Users' Guide at <https://www.census.gov/programs-surveys/sipp/guidance/users-guide.html>
# Note the 'select' statement in the first use of fread(). Most machines do not have enough memory to read
# the entire SIPP file into memory. Use a 'select' statement to read in only the columns you are interested in using.
# If you still encounter an out-of-memory error, you must select less columns or less observations.
# Load the "data.table", "dplyr", and "bit64" libraries. Use install.packages function if you don't already have these installed.
library("data.table")
##
## Attaching package: 'data.table'
## The following object is masked from 'package:base':
##
## %notin%
library("bit64")
## ********************************************************
## R-core is collecting use cases for 64-bit integers as they explore native support for these vectors.
##
## See https://stat.ethz.ch/pipermail/r-devel/2026-July/084631.html and reach out to Luke Tierney (luke-tierney@uiowa.edu).
## ********************************************************
##
## Attaching package: 'bit64'
## The following object is masked from 'package:utils':
##
## hashtab
## The following objects are masked from 'package:base':
##
## %in%, :, array, as.factor, as.ordered, colSums, factor, intersect,
## is.double, is.element, match, matrix, order, rank, rowSums,
## setdiff, setequal, table, union
library("dplyr")
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:bit64':
##
## intersect, setdiff, setequal, union
## The following objects are masked from 'package:data.table':
##
## between, first, last
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Store the text "pu2025.csv" in a name called ds
ds <- c("pu2025.csv")
# The file is pipe-delimited even though it's named .csv
pu <- fread(ds, sep = "|", select = c("SSUID", "ERESIDENCEID", "PNUM", "MONTHCODE", "SPANEL", "WPFINWGT", "ESEEING", "RFOODS", "RFOODR", "TAGE", "ESEX", "THHLDSTATUS"))
# Out of 5,203 variables, 12 variables were selected. The first six in the above line represent ID and structure variables. SSUID is sample unit ID with PNUM identifies a person and ERESIDENCEID identifies a household. PNUM is person number within the sample unit. MONTHCODE is reference month (1–12). SPANEL is panel year (2022-2025). WPFINWGT is the final person weight.The next six represent ESEEING blind or serious difficulty seeing even with glasses/contacts. RFOODS food security status recode: 1 high/marginal, 2 low, 3 very low. RFOODR is the raw food security score a count of affirmative responses (0–6). TAGE is age as of last birthday (capped at 90 for confidentiality). ESEX is sex with 1 Male, 2 Female. THHLDSTATUS represents household status and was added in the midst of coding due to needing to prove why I received 5,423 NAs.
# Make sure all the column names are upper-case
names(pu) <- toupper(names(pu))
# Preview the data
head(pu, 20)
## SSUID ERESIDENCEID PNUM MONTHCODE SPANEL WPFINWGT ESEEING RFOODS
## <i64> <int> <int> <int> <int> <num> <int> <int>
## 1: 11428525324 100001 101 1 2024 8290.772 2 1
## 2: 11428525324 100001 101 2 2024 8476.619 2 1
## 3: 11428525324 100001 101 3 2024 9238.426 2 1
## 4: 11428525324 100001 101 4 2024 9371.330 2 1
## 5: 11428525324 100001 101 5 2024 9547.140 2 1
## 6: 11428525324 100001 101 6 2024 9337.827 2 1
## 7: 11428525324 100001 101 7 2024 9096.493 2 1
## 8: 11428525324 100001 101 8 2024 9310.043 2 1
## 9: 11428525324 100001 101 9 2024 9209.630 2 1
## 10: 11428525324 100001 101 10 2024 9150.450 2 1
## 11: 11428525324 100001 101 11 2024 9195.871 2 1
## 12: 11428525324 100001 101 12 2024 9433.126 2 1
## 13: 11428534325 100001 101 1 2025 4473.576 2 3
## 14: 11428534325 100001 101 2 2025 4561.484 2 3
## 15: 11428534325 100001 101 3 2025 4761.070 2 3
## 16: 11428534325 100001 101 4 2025 5111.557 2 3
## 17: 11428534325 100001 101 5 2025 5001.163 2 3
## 18: 11428534325 100001 101 6 2025 4933.283 2 3
## 19: 11428534325 100001 101 7 2025 4894.891 2 3
## 20: 11428534325 100001 101 8 2025 4716.378 2 3
## SSUID ERESIDENCEID PNUM MONTHCODE SPANEL WPFINWGT ESEEING RFOODS
## <i64> <int> <int> <int> <int> <num> <int> <int>
## RFOODR TAGE ESEX THHLDSTATUS
## <int> <int> <int> <int>
## 1: 0 70 1 1
## 2: 0 70 1 1
## 3: 0 70 1 1
## 4: 0 70 1 1
## 5: 0 70 1 1
## 6: 0 70 1 1
## 7: 0 70 1 1
## 8: 0 70 1 1
## 9: 0 70 1 1
## 10: 0 70 1 1
## 11: 0 70 1 1
## 12: 0 70 1 1
## 13: 6 50 1 2
## 14: 6 50 1 2
## 15: 6 50 1 2
## 16: 6 50 1 2
## 17: 6 50 1 2
## 18: 6 50 1 2
## 19: 6 50 1 2
## 20: 6 50 1 2
## RFOODR TAGE ESEX THHLDSTATUS
## <int> <int> <int> <int>
# Rows are person-months, not people therefore 379,215 rows equals 32,052 people.
nrow(pu)
## [1] 379215
n_distinct(pu$SSUID, pu$PNUM)
## [1] 32052
n_distinct(pu$SSUID, pu$ERESIDENCEID)
## [1] 15215
summary(pu)
## SSUID ERESIDENCEID PNUM MONTHCODE
## Min. : 11428525324 Min. :100001 Min. :101.0 Min. : 1.000
## 1st Qu.:33286052753124 1st Qu.:100001 1st Qu.:101.0 1st Qu.: 3.000
## Median :66728586009222 Median :100001 Median :102.0 Median : 6.000
## Mean :56487541761701 Mean :115599 Mean :111.3 Mean : 6.482
## 3rd Qu.:87686017231924 3rd Qu.:100001 3rd Qu.:103.0 3rd Qu.: 9.000
## Max. :88199599599922 Max. :400005 Max. :405.0 Max. :12.000
##
## SPANEL WPFINWGT ESEEING RFOODS
## Min. :2022 Min. : 0 Min. :1.00 Min. :1.000
## 1st Qu.:2022 1st Qu.: 5673 1st Qu.:2.00 1st Qu.:1.000
## Median :2023 Median : 8573 Median :2.00 Median :1.000
## Mean :2023 Mean : 10505 Mean :1.95 Mean :1.157
## 3rd Qu.:2025 3rd Qu.: 13105 3rd Qu.:2.00 3rd Qu.:1.000
## Max. :2025 Max. :133335 Max. :2.00 Max. :3.000
## NAs :5423
## RFOODR TAGE ESEX THHLDSTATUS
## Min. :0.0000 Min. : 0.00 Min. :1.000 Min. :1.000
## 1st Qu.:0.0000 1st Qu.:25.00 1st Qu.:1.000 1st Qu.:1.000
## Median :0.0000 Median :46.00 Median :2.000 Median :1.000
## Mean :0.4814 Mean :45.31 Mean :1.513 Mean :1.365
## 3rd Qu.:0.0000 3rd Qu.:66.00 3rd Qu.:2.000 3rd Qu.:2.000
## Max. :6.0000 Max. :90.00 Max. :2.000 Max. :6.000
##
# Descriptive stats shows 5,423 NAs in ESEEING, these NAs were not asked because they were outside the variable's universe, per the dictionary.No other variables report NA.
na_rows <- pu %>% filter(is.na(ESEEING))
table(na_rows$TAGE)
##
## 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
## 693 31 67 23 32 32 44 30 21 29 42 22 24 8 30 35 58 33 179 282
## 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
## 142 140 122 166 138 118 83 74 141 160 71 75 86 103 36 57 56 68 59 90
## 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
## 45 73 27 16 9 51 35 24 5 12 41 21 12 24 20 31 15 30 48 31
## 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
## 28 13 20 48 39 11 28 14 20 15 39 24 43 33 66 67 69 33 67 21
## 80 81 82 83 84 85 86 87 88 89 90
## 54 40 5 12 37 58 20 11 86 47 85
sum(na_rows$TAGE>= 1)
## [1] 4730
# 4730 are the NA rows aged 1 or older. Age doesn't explain them.
table(na_rows$THHLDSTATUS, na_rows$TAGE >= 1)
##
## FALSE TRUE
## 1 10 0
## 2 677 0
## 3 0 1335
## 4 6 2909
## 5 0 140
## 6 0 346
# All 5,423 NAs fall outside ESEEING's universe. 687 failed age only, 4,730 failed status only, 6 failed both.
table(pu$SPANEL)
##
## 2022 2023 2024 2025
## 120652 69613 75519 113431
spanel_2025 <- pu %>% filter(SPANEL == 2025)
nrow(spanel_2025)
## [1] 113431
# Reference years differ across panels; weights are designed within panel. Kept 2025 for recency, sample from 2025 is 113,431 person-months.
n_distinct(spanel_2025$SSUID, spanel_2025$PNUM)
## [1] 9490
month_1 <- spanel_2025 %>% filter(MONTHCODE == 1)
nrow(month_1)
## [1] 9419
# 9,490 people in the 2025 panel, one row per person is set, nrow produces 71-person gap.
first_months <- spanel_2025 %>% group_by(SSUID, PNUM) %>% summarise(first_month =min(MONTHCODE))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by SSUID and PNUM.
## ℹ Output is grouped by SSUID.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(SSUID, PNUM))` for per-operation grouping
## (`?dplyr::dplyr_by`) instead.
table(first_months$first_month)
##
## 1 2 3 5 6 7 8 9 10 11 12
## 9419 5 6 6 13 8 8 7 5 5 8
# All 71 missing people have their first record in the data after January, spread from February to December. None of them have a January row, so filtering to January drops them. Data doesn't show why (e.g., birth, moving, etc.)
vision_food <- month_1 %>% select(RFOODR, ESEEING)
cor(vision_food)
## RFOODR ESEEING
## RFOODR 1.00000000 -0.06769058
## ESEEING -0.06769058 1.00000000
# Negative correlation that is weak.
pairs(~RFOODR+ESEEING, data=vision_food)

table(vision_food$RFOODR, vision_food$ESEEING)
##
## 1 2
## 0 278 7465
## 1 36 523
## 2 28 332
## 3 16 136
## 4 12 130
## 5 13 147
## 6 23 280
# ESEEING has 2 values, RFOODR has 7 values.
# Kendall's TAU is being used since RFOODR is not a normal distribution 7,743 of 9,419 RFOODR values are 0. 7,465 people share the same pair of values. However the sample size is large.
cor.test(vision_food$RFOODR, vision_food$ESEEING, method="kendall")
##
## Kendall's rank correlation tau
##
## data: vision_food$RFOODR and vision_food$ESEEING
## z = -7.4911, p-value = 6.829e-14
## alternative hypothesis: true tau is not equal to 0
## sample estimates:
## tau
## -0.07455382
- RFOODR was tested against ESEEING in the month_1 data frame where n
= 9,419
- Correlation test showed a weak negative relationship. Kendall’s Tau
yielded a highly significant p-value of p = 6.829e-14 and tau = -0.075
which means people who are vision impaired have higher food insecurity
scores.
- Kendall’s TAU was used since RFOODR is not a normal distribution.
7,743 of 9,419 RFOODR values are 0. 7,465 people share the same pair of
values. However the sample size is large with n = 9,419
- Despite there being a correlation, this result does not allow us to
assert a causal relationship between vision impairment and food
insecurity.