dplyr中if_else语句输出异常问题排查求助
Hey there, let’s dig into why your dplyr::if_else() is acting up with that longitudinal participant follow-up data. I’ve tackled similar survey year mapping headaches before, so here are the most common issues to check and fix:
if_else() Unlike base R’s ifelse(), dplyr::if_else() enforces exact matching data types for its true and false outputs. If you’re returning, say, a date for the true case and a character string for false, it’ll either throw an error or silently coerce values in unexpected ways.
- Fix: Make sure both branches return the same type. If you need to fill missing survey years, use type-specific
NAvalues (e.g.,NA_Date_for dates,NA_integer_for integers). - Example:
# Bad: Mixed data types break if_else() df %>% mutate(survey_year = if_else(survey_start, as.Date("2023-01-01"), "Not applicable")) # Good: Consistent date type throughout df %>% mutate(survey_year = if_else(survey_start, as.Date("2023-01-01"), NA_Date_))
Since you’re working with per-person longitudinal data, forgetting to group by participant ID will make if_else() apply logic across the entire dataset instead of per individual. This leads to misaligned survey year assignments.
- Fix: Add
group_by(participant_id)(replace with your actual ID column) before your mutate step, then usefill()to propagate the survey year to subsequent entries for that participant. - Example:
df %>% group_by(participant_id) %>% mutate(survey_year = if_else(survey_start, lubridate::year(survey_date), NA_integer_)) %>% fill(survey_year, .direction = "down") %>% # Fills survey year to all follow-up rows ungroup()
survey_start flag If survey_start isn’t a clean logical (TRUE/FALSE) column—for example, it has NAs, character values like "Yes"/"No", or numeric codes—if_else() won’t behave as intended.
- Fix: First check for unexpected values with
table(df$survey_start), then convert it to a logical column if needed:df %>% mutate(survey_start = case_when( survey_start == "Survey Start" ~ TRUE, survey_start == "Follow-Up" ~ FALSE, TRUE ~ NA # Catch any unclassified values ))
If participants have multiple survey_start events (e.g., 1-year, 2-year follow-ups), basic grouping might overwrite earlier survey years instead of creating distinct periods.
- Fix: Use
cumsum()to generate a unique survey period ID per participant, then group by both ID and period to keep years separate:df %>% group_by(participant_id) %>% mutate(survey_period = cumsum(survey_start)) # Increments at each new survey start group_by(participant_id, survey_period) %>% mutate(survey_year = if_else(survey_start, lubridate::year(survey_date), NA_integer_)) %>% fill(survey_year) %>% ungroup()
内容的提问来源于stack exchange,提问作者K. Wamae

