# 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
  1. RFOODR was tested against ESEEING in the month_1 data frame where n = 9,419
  2. 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.
  3. 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
  4. Despite there being a correlation, this result does not allow us to assert a causal relationship between vision impairment and food insecurity.