使用mutate与case_when转换字符型工龄为数值型报错求助
case_when Conversion for Service Length Let's break down what went wrong with your code and walk through the correct approach to keep your original character variable while adding a numeric version.
Why You Got That Error
The core issues in your code are two key missteps:
- Inconsistent return types in
case_when: Most branches return numeric values (like0.99,2, etc.), but the finalTRUE ~ "NA"returns a character string.case_whenrequires all outputs to match the same data type, hence the error saying it expected a double (numeric) vector instead of a character one. - Incorrect
mutatesyntax: You tried comparingdf$length_of_serviceto thecase_whenresult, which doesn't make sense here—you need to assign a new variable name instead. Also, when using dplyr pipes (%>%), you don't need to referencedf$inside functions likemutate; just use the variable name directly.
Correct Implementation
You don't need to create a separate empty data frame and merge it later—dplyr's mutate lets you add a new variable directly to your original data frame, preserving the existing length_of_service variable automatically.
Here's the fixed code (assuming your original data frame is named df):
library(dplyr) # Add a numeric version of length_of_service while keeping the original df <- df %>% mutate( los_numeric = case_when( length_of_service == "< 1 year" ~ 0.99, length_of_service == "2 years" ~ 2, length_of_service == "3 years" ~ 3, length_of_service == "4 years" ~ 4, length_of_service == "5 years" ~ 5, length_of_service == "6 years" ~ 6, length_of_service == "7 years" ~ 7, length_of_service == "8 years" ~ 8, length_of_service == "9 years" ~ 9, length_of_service == "10+ years" ~ 10, # Use numeric NA for unmatched values to keep type consistency TRUE ~ NA_real_ ) )
This code retains your original length_of_service (character type) and adds a new numeric column los_numeric with your converted values.
Optimization Tips
Your current case_when has a lot of repetitive lines. You can simplify it using string manipulation to extract numeric values instead of writing a line for every year:
library(dplyr) library(stringr) df <- df %>% mutate( los_numeric = case_when( length_of_service == "< 1 year" ~ 0.99, length_of_service == "10+ years" ~ 10, # Extract digits from the string and convert to numeric for all other cases TRUE ~ as.numeric(str_extract(length_of_service, "\\d+")) ) )
This works because all your other values follow the pattern "X years"—str_extract(length_of_service, "\\d+") pulls out the number, and as.numeric converts it to a numeric value. This reduces code repetition and makes it easier to maintain if new categories are added later.
Additional best practices:
- Always use
NA_real_(numeric NA) instead of"NA"(character) when working with numeric vectors to avoid type conflicts. - After running the code, check for
NAvalues inlos_numericto confirm you didn't miss any categories in yourcase_whenlogic.
内容的提问来源于stack exchange,提问作者Data Science Analytics Manager

