R语言变量创建两类问题:缺失值处理与多条件逻辑实现
Hey there! Let's work through your two R variable creation questions, making sure we handle those coded missing values (-99, -98) and actual NAs correctly—since leaving them unaddressed can mess up your binary variables.
1. Fixing Missing Values for the new Binary Variable
Your original code df0$new <- ifelse(df0$old=="yes",1,0) will incorrectly assign 0 to any -99, -98, or NA values in old, treating them as "no" when they're actually missing data. Here's how to fix this properly:
First, it's best practice to convert those coded missing values to R's native NA—this makes all missing value handling consistent across functions:
# Recode -99, -98, and existing NA to R's NA df0$old <- ifelse(df0$old %in% c(-99, -98, NA), NA, df0$old)
Then, you have a few clean options to create new:
- Base R shortcut: Convert a logical vector to integers (since
TRUEbecomes 1,FALSEbecomes 0, andNAstaysNA):df0$new <- as.integer(df0$old == "yes") - Explicit
ifelse: If you prefer more clarity:df0$new <- ifelse(df0$old == "yes", 1, ifelse(is.na(df0$old), NA, 0)) - dplyr
case_when: Great for readability if you're using the tidyverse:library(dplyr) df0 <- df0 %>% mutate(new = case_when( old == "yes" ~ 1, !is.na(old) ~ 0, TRUE ~ NA_integer_ # Catch-all for missing values ))
2. Creating z with OR Logic + Missing Value Handling
Your goal is to set z=1 if any of q1-q5 equals 1, z=0 only if all are non-missing and none equal 1, and z=NA if there are missing values but no 1s. Here's how to do this right:
First, recode those coded missing values in q1-q5 to NA just like we did for old:
# Recode -99/-98 to NA across all q1-q5 columns df0[, paste0("q", 1:5)] <- lapply(df0[, paste0("q", 1:5)], function(x) { ifelse(x %in% c(-99, -98, NA), NA, x) })
Now, two solid approaches for the OR logic:
- Base R with
rowSums:# First set z=1 if any q equals 1 (ignoring NA for the check) df0$z <- as.integer(rowSums(df0[, paste0("q", 1:5)] == 1, na.rm = TRUE) > 0) # Fix cases where all q1-q5 are NA (set z to NA instead of 0) df0$z <- ifelse(rowSums(is.na(df0[, paste0("q", 1:5)])) == 5, NA, df0$z) - dplyr
if_any(cleanest!): Theif_anyfunction was built exactly for this "any column meets condition" scenario:df0 <- df0 %>% mutate(z = case_when( if_any(starts_with("q"), ~ .x == 1) ~ 1, # Any q equals 1 if_all(starts_with("q"), ~ !is.na(.x)) ~ 0, # All q are non-missing and none are 1 TRUE ~ NA_integer_ # Missing values present, no q equals 1 ))
内容的提问来源于stack exchange,提问作者bvowe

